+++ /dev/null
-#
-# Copyright (C) 2007 - 2008 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-include $(TOPDIR)/rules.mk
-include $(INCLUDE_DIR)/kernel.mk
-
-PKG_NAME:=kmod-libertas
-PKG_RELEASE:=1
-
-include $(INCLUDE_DIR)/package.mk
-
-# XXX: current version needs 'get_unaligned_le16' helper introduced in 2.6.26
-define KernelPackage/libertas
- SUBMENU:=Wireless Drivers
- DEPENDS:=+kmod-ieee80211 @LINUX_2_6 @!LINUX_2_6_21||!LINUX_2_6_25
- TITLE:=Marvell 88W8015 Wireless Driver
- FILES:= \
- $(PKG_BUILD_DIR)/libertas.$(LINUX_KMOD_SUFFIX) \
- $(PKG_BUILD_DIR)/usb8xxx.$(LINUX_KMOD_SUFFIX)
- AUTOLOAD:=$(call AutoLoad,30,libertas usb8xxx)
-endef
-
-FW_NAME:=usb8388-5.110.22.p23.bin
-
-define Download/firmware
- URL:=http://dev.laptop.org/pub/firmware/libertas
- FILE:=$(FW_NAME)
- MD5SUM=5e38f55719df3d0c58dd3bd02575a09c
-endef
-
-define Build/Prepare
- mkdir -p $(PKG_BUILD_DIR)
- $(CP) ./src/* $(PKG_BUILD_DIR)/
- $(Build/Patch)
-endef
-
-define Build/Compile
- $(MAKE) -C "$(LINUX_DIR)" \
- CROSS_COMPILE="$(TARGET_CROSS)" \
- ARCH="$(LINUX_KARCH)" \
- SUBDIRS="$(PKG_BUILD_DIR)" \
- CONFIG_LIBERTAS=m \
- CONFIG_LIBERTAS_USB=m \
- EXTRA_CFLAGS="-I$(PKG_BUILD_DIR) -DCONFIG_LIBERTAS_DEBUG -I$(STAGING_DIR)/usr/include/mac80211" \
- modules
-endef
-
-define KernelPackage/libertas/install
- $(INSTALL_DIR) $(1)/lib/firmware
- $(INSTALL_BIN) $(DL_DIR)/$(FW_NAME) $(1)/lib/firmware/usb8388.bin
- $(INSTALL_DATA) ./files/LICENSE $(1)/lib/firmware/usb8388.LICENSE
-endef
-
-$(eval $(call KernelPackage,libertas))
-$(eval $(call Download,firmware))
+++ /dev/null
-Copyright (c) 2006, One Laptop per Child and Marvell Corporation.\r
-All rights reserved.\r
-\r
-Redistribution. Redistribution and use in binary form, without \r
-modification, are permitted provided that the following conditions are \r
-met:\r
-\r
-* Redistributions must reproduce the above copyright notice and the \r
- following disclaimer in the documentation and/or other materials \r
- provided with the distribution.\r
-* Neither the name of Marvell Corporation nor the names of its suppliers \r
- may be used to endorse or promote products derived from this software \r
- without specific prior written permission.
-* No reverse engineering, decompilation, or disassembly of this software \r
- is permitted.
-* You may not use or attempt to use this software in conjunction with
- any product that is offered by a third party as a replacement,
- substitute or alternative to a Marvell Product where a Marvell Product
- is defined as a proprietary wireless LAN embedded client solution of
- Marvell or a Marvell Affiliate.\r
-\r
-DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \r
-CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, \r
-BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \r
-FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, \r
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS \r
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND \r
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR \r
-TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE \r
-USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH \r
-DAMAGE.\r
+++ /dev/null
-diff --git a/scan.c b/scan.c
-index 387d487..d9cde10 100644
---- a/scan.c
-+++ b/scan.c
-@@ -4,6 +4,7 @@
- * IOCTL handlers as well as command preperation and response routines
- * for sending scan commands to the firmware.
- */
-+#include <linux/version.h>
- #include <linux/etherdevice.h>
- #include <asm/unaligned.h>
-
-@@ -13,6 +14,14 @@
- #include "scan.h"
- #include "cmd.h"
-
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-+#define IWE(func, ...) func(info, __VA_ARGS__)
-+#define LCP_LEN iwe_stream_lcp_len(info)
-+#else
-+#define IWE(func, ...) func(__VA_ARGS__)
-+#define LCP_LEN IW_EV_LCP_LEN
-+#endif
-+
- //! Approximate amount of data needed to pass a scan result back to iwlist
- #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
- + IW_ESSID_MAX_SIZE \
-@@ -776,6 +785,7 @@ out:
- #define MAX_CUSTOM_LEN 64
-
- static inline char *lbs_translate_scan(struct lbs_private *priv,
-+ struct iw_request_info *info,
- char *start, char *stop,
- struct bss_descriptor *bss)
- {
-@@ -801,24 +811,24 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
-- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
-+ start = IWE(iwe_stream_add_event, start, stop, &iwe, IW_EV_ADDR_LEN);
-
- /* SSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
-- start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
-+ start = IWE(iwe_stream_add_point, start, stop, &iwe, bss->ssid);
-
- /* Mode */
- iwe.cmd = SIOCGIWMODE;
- iwe.u.mode = bss->mode;
-- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
-+ start = IWE(iwe_stream_add_event, start, stop, &iwe, IW_EV_UINT_LEN);
-
- /* Frequency */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = (long)cfp->freq * 100000;
- iwe.u.freq.e = 1;
-- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
-+ start = IWE(iwe_stream_add_event, start, stop, &iwe, IW_EV_FREQ_LEN);
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
-@@ -852,7 +862,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
- nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
- iwe.u.qual.level = CAL_RSSI(snr, nf);
- }
-- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
-+ start = IWE(iwe_stream_add_event, start, stop, &iwe, IW_EV_QUAL_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
-@@ -862,9 +872,9 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- }
- iwe.u.data.length = 0;
-- start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
-+ start = IWE(iwe_stream_add_point, start, stop, &iwe, bss->ssid);
-
-- current_val = start + IW_EV_LCP_LEN;
-+ current_val = start + LCP_LEN;
-
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = 0;
-@@ -874,19 +884,19 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
- for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
- /* Bit rate given in 500 kb/s units */
- iwe.u.bitrate.value = bss->rates[j] * 500000;
-- current_val = iwe_stream_add_value(start, current_val,
-+ current_val = IWE(iwe_stream_add_value, start, current_val,
- stop, &iwe, IW_EV_PARAM_LEN);
- }
- if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
- && !lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
- bss->ssid, bss->ssid_len)) {
- iwe.u.bitrate.value = 22 * 500000;
-- current_val = iwe_stream_add_value(start, current_val,
-+ current_val = IWE(iwe_stream_add_value, start, current_val,
- stop, &iwe, IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
-- if((current_val - start) > IW_EV_LCP_LEN)
-+ if((current_val - start) > LCP_LEN)
- start = current_val;
-
- memset(&iwe, 0, sizeof(iwe));
-@@ -895,7 +905,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
- memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = bss->wpa_ie_len;
-- start = iwe_stream_add_point(start, stop, &iwe, buf);
-+ start = IWE(iwe_stream_add_point, start, stop, &iwe, buf);
- }
-
- memset(&iwe, 0, sizeof(iwe));
-@@ -904,7 +914,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
- memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = bss->rsn_ie_len;
-- start = iwe_stream_add_point(start, stop, &iwe, buf);
-+ start = IWE(iwe_stream_add_point, start, stop, &iwe, buf);
- }
-
- if (bss->mesh) {
-@@ -915,7 +925,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
- p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
- iwe.u.data.length = p - custom;
- if (iwe.u.data.length)
-- start = iwe_stream_add_point(start, stop, &iwe, custom);
-+ start = IWE(iwe_stream_add_point, start, stop, &iwe, custom);
- }
-
- out:
-@@ -1036,7 +1046,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
- }
-
- /* Translate to WE format this entry */
-- next_ev = lbs_translate_scan(priv, ev, stop, iter_bss);
-+ next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss);
- if (next_ev == NULL)
- continue;
- ev = next_ev;
+++ /dev/null
-/**
- * This file contains functions for 802.11D.
- */
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/wireless.h>
-
-#include "host.h"
-#include "decl.h"
-#include "11d.h"
-#include "dev.h"
-#include "wext.h"
-
-#define TX_PWR_DEFAULT 10
-
-static struct region_code_mapping region_code_mapping[] = {
- {"US ", 0x10}, /* US FCC */
- {"CA ", 0x10}, /* IC Canada */
- {"SG ", 0x10}, /* Singapore */
- {"EU ", 0x30}, /* ETSI */
- {"AU ", 0x30}, /* Australia */
- {"KR ", 0x30}, /* Republic Of Korea */
- {"ES ", 0x31}, /* Spain */
- {"FR ", 0x32}, /* France */
- {"JP ", 0x40}, /* Japan */
-};
-
-/* Following 2 structure defines the supported channels */
-static struct chan_freq_power channel_freq_power_UN_BG[] = {
- {1, 2412, TX_PWR_DEFAULT},
- {2, 2417, TX_PWR_DEFAULT},
- {3, 2422, TX_PWR_DEFAULT},
- {4, 2427, TX_PWR_DEFAULT},
- {5, 2432, TX_PWR_DEFAULT},
- {6, 2437, TX_PWR_DEFAULT},
- {7, 2442, TX_PWR_DEFAULT},
- {8, 2447, TX_PWR_DEFAULT},
- {9, 2452, TX_PWR_DEFAULT},
- {10, 2457, TX_PWR_DEFAULT},
- {11, 2462, TX_PWR_DEFAULT},
- {12, 2467, TX_PWR_DEFAULT},
- {13, 2472, TX_PWR_DEFAULT},
- {14, 2484, TX_PWR_DEFAULT}
-};
-
-static u8 lbs_region_2_code(u8 *region)
-{
- u8 i;
-
- for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
- region[i] = toupper(region[i]);
-
- for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
- if (!memcmp(region, region_code_mapping[i].region,
- COUNTRY_CODE_LEN))
- return (region_code_mapping[i].code);
- }
-
- /* default is US */
- return (region_code_mapping[0].code);
-}
-
-static u8 *lbs_code_2_region(u8 code)
-{
- u8 i;
-
- for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
- if (region_code_mapping[i].code == code)
- return (region_code_mapping[i].region);
- }
- /* default is US */
- return (region_code_mapping[0].region);
-}
-
-/**
- * @brief This function finds the nrchan-th chan after the firstchan
- * @param band band
- * @param firstchan first channel number
- * @param nrchan number of channels
- * @return the nrchan-th chan number
-*/
-static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
-/*find the nrchan-th chan after the firstchan*/
-{
- u8 i;
- struct chan_freq_power *cfp;
- u8 cfp_no;
-
- cfp = channel_freq_power_UN_BG;
- cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG);
-
- for (i = 0; i < cfp_no; i++) {
- if ((cfp + i)->channel == firstchan) {
- lbs_deb_11d("firstchan found\n");
- break;
- }
- }
-
- if (i < cfp_no) {
- /*if beyond the boundary */
- if (i + nrchan < cfp_no) {
- *chan = (cfp + i + nrchan)->channel;
- return 1;
- }
- }
-
- return 0;
-}
-
-/**
- * @brief This function Checks if chan txpwr is learned from AP/IBSS
- * @param chan chan number
- * @param parsed_region_chan pointer to parsed_region_chan_11d
- * @return TRUE; FALSE
-*/
-static u8 lbs_channel_known_11d(u8 chan,
- struct parsed_region_chan_11d * parsed_region_chan)
-{
- struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr;
- u8 nr_chan = parsed_region_chan->nr_chan;
- u8 i = 0;
-
- lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)chanpwr,
- sizeof(struct chan_power_11d) * nr_chan);
-
- for (i = 0; i < nr_chan; i++) {
- if (chan == chanpwr[i].chan) {
- lbs_deb_11d("found chan %d\n", chan);
- return 1;
- }
- }
-
- lbs_deb_11d("chan %d not found\n", chan);
- return 0;
-}
-
-u32 lbs_chan_2_freq(u8 chan)
-{
- struct chan_freq_power *cf;
- u16 i;
- u32 freq = 0;
-
- cf = channel_freq_power_UN_BG;
-
- for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) {
- if (chan == cf[i].channel)
- freq = cf[i].freq;
- }
-
- return freq;
-}
-
-static int generate_domain_info_11d(struct parsed_region_chan_11d
- *parsed_region_chan,
- struct lbs_802_11d_domain_reg *domaininfo)
-{
- u8 nr_subband = 0;
-
- u8 nr_chan = parsed_region_chan->nr_chan;
- u8 nr_parsedchan = 0;
-
- u8 firstchan = 0, nextchan = 0, maxpwr = 0;
-
- u8 i, flag = 0;
-
- memcpy(domaininfo->countrycode, parsed_region_chan->countrycode,
- COUNTRY_CODE_LEN);
-
- lbs_deb_11d("nrchan %d\n", nr_chan);
- lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)parsed_region_chan,
- sizeof(struct parsed_region_chan_11d));
-
- for (i = 0; i < nr_chan; i++) {
- if (!flag) {
- flag = 1;
- nextchan = firstchan =
- parsed_region_chan->chanpwr[i].chan;
- maxpwr = parsed_region_chan->chanpwr[i].pwr;
- nr_parsedchan = 1;
- continue;
- }
-
- if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 &&
- parsed_region_chan->chanpwr[i].pwr == maxpwr) {
- nextchan++;
- nr_parsedchan++;
- } else {
- domaininfo->subband[nr_subband].firstchan = firstchan;
- domaininfo->subband[nr_subband].nrchan =
- nr_parsedchan;
- domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
- nr_subband++;
- nextchan = firstchan =
- parsed_region_chan->chanpwr[i].chan;
- maxpwr = parsed_region_chan->chanpwr[i].pwr;
- }
- }
-
- if (flag) {
- domaininfo->subband[nr_subband].firstchan = firstchan;
- domaininfo->subband[nr_subband].nrchan = nr_parsedchan;
- domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
- nr_subband++;
- }
- domaininfo->nr_subband = nr_subband;
-
- lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
- lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo,
- COUNTRY_CODE_LEN + 1 +
- sizeof(struct ieeetypes_subbandset) * nr_subband);
- return 0;
-}
-
-/**
- * @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS
- * @param region_chan pointer to struct region_channel
- * @param *parsed_region_chan pointer to parsed_region_chan_11d
- * @return N/A
-*/
-static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_chan,
- struct parsed_region_chan_11d *
- parsed_region_chan)
-{
- u8 i;
- struct chan_freq_power *cfp;
-
- if (region_chan == NULL) {
- lbs_deb_11d("region_chan is NULL\n");
- return;
- }
-
- cfp = region_chan->CFP;
- if (cfp == NULL) {
- lbs_deb_11d("cfp is NULL \n");
- return;
- }
-
- parsed_region_chan->band = region_chan->band;
- parsed_region_chan->region = region_chan->region;
- memcpy(parsed_region_chan->countrycode,
- lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
-
- lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region,
- parsed_region_chan->band);
-
- for (i = 0; i < region_chan->nrcfp; i++, cfp++) {
- parsed_region_chan->chanpwr[i].chan = cfp->channel;
- parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower;
- lbs_deb_11d("chan %d, pwr %d\n",
- parsed_region_chan->chanpwr[i].chan,
- parsed_region_chan->chanpwr[i].pwr);
- }
- parsed_region_chan->nr_chan = region_chan->nrcfp;
-
- lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan);
-
- return;
-}
-
-/**
- * @brief generate parsed_region_chan from Domain Info learned from AP/IBSS
- * @param region region ID
- * @param band band
- * @param chan chan
- * @return TRUE;FALSE
-*/
-static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
-{
- struct chan_freq_power *cfp;
- int cfp_no;
- u8 idx;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_11D);
-
- cfp = lbs_get_region_cfp_table(region, &cfp_no);
- if (cfp == NULL)
- return 0;
-
- for (idx = 0; idx < cfp_no; idx++) {
- if (chan == (cfp + idx)->channel) {
- /* If Mrvl Chip Supported? */
- if ((cfp + idx)->unsupported) {
- ret = 0;
- } else {
- ret = 1;
- }
- goto done;
- }
- }
-
- /*chan is not in the region table */
-
-done:
- lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function checks if chan txpwr is learned from AP/IBSS
- * @param chan chan number
- * @param parsed_region_chan pointer to parsed_region_chan_11d
- * @return 0
-*/
-static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
- countryinfo,
- u8 band,
- struct parsed_region_chan_11d *
- parsed_region_chan)
-{
- u8 nr_subband, nrchan;
- u8 lastchan, firstchan;
- u8 region;
- u8 curchan = 0;
-
- u8 idx = 0; /*chan index in parsed_region_chan */
-
- u8 j, i;
-
- lbs_deb_enter(LBS_DEB_11D);
-
- /*validation Rules:
- 1. valid region Code
- 2. First Chan increment
- 3. channel range no overlap
- 4. channel is valid?
- 5. channel is supported by region?
- 6. Others
- */
-
- lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30);
-
- if ((*(countryinfo->countrycode)) == 0
- || (countryinfo->len <= COUNTRY_CODE_LEN)) {
- /* No region Info or Wrong region info: treat as No 11D info */
- goto done;
- }
-
- /*Step1: check region_code */
- parsed_region_chan->region = region =
- lbs_region_2_code(countryinfo->countrycode);
-
- lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
- lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode,
- COUNTRY_CODE_LEN);
-
- parsed_region_chan->band = band;
-
- memcpy(parsed_region_chan->countrycode, countryinfo->countrycode,
- COUNTRY_CODE_LEN);
-
- nr_subband = (countryinfo->len - COUNTRY_CODE_LEN) /
- sizeof(struct ieeetypes_subbandset);
-
- for (j = 0, lastchan = 0; j < nr_subband; j++) {
-
- if (countryinfo->subband[j].firstchan <= lastchan) {
- /*Step2&3. Check First Chan Num increment and no overlap */
- lbs_deb_11d("chan %d>%d, overlap\n",
- countryinfo->subband[j].firstchan, lastchan);
- continue;
- }
-
- firstchan = countryinfo->subband[j].firstchan;
- nrchan = countryinfo->subband[j].nrchan;
-
- for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
- /*step4: channel is supported? */
-
- if (!lbs_get_chan_11d(firstchan, i, &curchan)) {
- /* Chan is not found in UN table */
- lbs_deb_11d("chan is not supported: %d \n", i);
- break;
- }
-
- lastchan = curchan;
-
- if (lbs_region_chan_supported_11d(region, curchan)) {
- /*step5: Check if curchan is supported by mrvl in region */
- parsed_region_chan->chanpwr[idx].chan = curchan;
- parsed_region_chan->chanpwr[idx].pwr =
- countryinfo->subband[j].maxtxpwr;
- idx++;
- } else {
- /*not supported and ignore the chan */
- lbs_deb_11d(
- "i %d, chan %d unsupported in region %x, band %d\n",
- i, curchan, region, band);
- }
- }
-
- /*Step6: Add other checking if any */
-
- }
-
- parsed_region_chan->nr_chan = idx;
-
- lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan);
- lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (u8 *) parsed_region_chan,
- 2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
-
-done:
- lbs_deb_enter(LBS_DEB_11D);
- return 0;
-}
-
-/**
- * @brief This function calculates the scan type for channels
- * @param chan chan number
- * @param parsed_region_chan pointer to parsed_region_chan_11d
- * @return PASSIVE if chan is unknown; ACTIVE if chan is known
-*/
-u8 lbs_get_scan_type_11d(u8 chan,
- struct parsed_region_chan_11d * parsed_region_chan)
-{
- u8 scan_type = CMD_SCAN_TYPE_PASSIVE;
-
- lbs_deb_enter(LBS_DEB_11D);
-
- if (lbs_channel_known_11d(chan, parsed_region_chan)) {
- lbs_deb_11d("found, do active scan\n");
- scan_type = CMD_SCAN_TYPE_ACTIVE;
- } else {
- lbs_deb_11d("not found, do passive scan\n");
- }
-
- lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type);
- return scan_type;
-
-}
-
-void lbs_init_11d(struct lbs_private *priv)
-{
- priv->enable11d = 0;
- memset(&(priv->parsed_region_chan), 0,
- sizeof(struct parsed_region_chan_11d));
- return;
-}
-
-/**
- * @brief This function sets DOMAIN INFO to FW
- * @param priv pointer to struct lbs_private
- * @return 0; -1
-*/
-static int set_domain_info_11d(struct lbs_private *priv)
-{
- int ret;
-
- if (!priv->enable11d) {
- lbs_deb_11d("dnld domain Info with 11d disabled\n");
- return 0;
- }
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
- if (ret)
- lbs_deb_11d("fail to dnld domain info\n");
-
- return ret;
-}
-
-/**
- * @brief This function setups scan channels
- * @param priv pointer to struct lbs_private
- * @param band band
- * @return 0
-*/
-int lbs_set_universaltable(struct lbs_private *priv, u8 band)
-{
- u16 size = sizeof(struct chan_freq_power);
- u16 i = 0;
-
- memset(priv->universal_channel, 0,
- sizeof(priv->universal_channel));
-
- priv->universal_channel[i].nrcfp =
- sizeof(channel_freq_power_UN_BG) / size;
- lbs_deb_11d("BG-band nrcfp %d\n",
- priv->universal_channel[i].nrcfp);
-
- priv->universal_channel[i].CFP = channel_freq_power_UN_BG;
- priv->universal_channel[i].valid = 1;
- priv->universal_channel[i].region = UNIVERSAL_REGION_CODE;
- priv->universal_channel[i].band = band;
- i++;
-
- return 0;
-}
-
-/**
- * @brief This function implements command CMD_802_11D_DOMAIN_INFO
- * @param priv pointer to struct lbs_private
- * @param cmd pointer to cmd buffer
- * @param cmdno cmd ID
- * @param cmdOption cmd action
- * @return 0
-*/
-int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
- struct cmd_ds_command *cmd, u16 cmdno,
- u16 cmdoption)
-{
- struct cmd_ds_802_11d_domain_info *pdomaininfo =
- &cmd->params.domaininfo;
- struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain;
- u8 nr_subband = priv->domainreg.nr_subband;
-
- lbs_deb_enter(LBS_DEB_11D);
-
- lbs_deb_11d("nr_subband=%x\n", nr_subband);
-
- cmd->command = cpu_to_le16(cmdno);
- pdomaininfo->action = cpu_to_le16(cmdoption);
- if (cmdoption == CMD_ACT_GET) {
- cmd->size =
- cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
- lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
- le16_to_cpu(cmd->size));
- goto done;
- }
-
- domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
- memcpy(domain->countrycode, priv->domainreg.countrycode,
- sizeof(domain->countrycode));
-
- domain->header.len =
- cpu_to_le16(nr_subband * sizeof(struct ieeetypes_subbandset) +
- sizeof(domain->countrycode));
-
- if (nr_subband) {
- memcpy(domain->subband, priv->domainreg.subband,
- nr_subband * sizeof(struct ieeetypes_subbandset));
-
- cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
- le16_to_cpu(domain->header.len) +
- sizeof(struct mrvlietypesheader) +
- S_DS_GEN);
- } else {
- cmd->size =
- cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
- }
-
- lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, le16_to_cpu(cmd->size));
-
-done:
- lbs_deb_enter(LBS_DEB_11D);
- return 0;
-}
-
-/**
- * @brief This function parses countryinfo from AP and download country info to FW
- * @param priv pointer to struct lbs_private
- * @param resp pointer to command response buffer
- * @return 0; -1
- */
-int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
- struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
- u16 action = le16_to_cpu(domaininfo->action);
- s16 ret = 0;
- u8 nr_subband = 0;
-
- lbs_deb_enter(LBS_DEB_11D);
-
- lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
- (int)le16_to_cpu(resp->size));
-
- nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
- sizeof(struct ieeetypes_subbandset);
-
- lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband);
-
- if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
- lbs_deb_11d("Invalid Numrer of Subband returned!!\n");
- return -1;
- }
-
- switch (action) {
- case CMD_ACT_SET: /*Proc Set action */
- break;
-
- case CMD_ACT_GET:
- break;
- default:
- lbs_deb_11d("Invalid action:%d\n", domaininfo->action);
- ret = -1;
- break;
- }
-
- lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function parses countryinfo from AP and download country info to FW
- * @param priv pointer to struct lbs_private
- * @return 0; -1
- */
-int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
- struct bss_descriptor * bss)
-{
- int ret;
-
- lbs_deb_enter(LBS_DEB_11D);
- if (priv->enable11d) {
- memset(&priv->parsed_region_chan, 0,
- sizeof(struct parsed_region_chan_11d));
- ret = parse_domain_info_11d(&bss->countryinfo, 0,
- &priv->parsed_region_chan);
-
- if (ret == -1) {
- lbs_deb_11d("error parsing domain_info from AP\n");
- goto done;
- }
-
- memset(&priv->domainreg, 0,
- sizeof(struct lbs_802_11d_domain_reg));
- generate_domain_info_11d(&priv->parsed_region_chan,
- &priv->domainreg);
-
- ret = set_domain_info_11d(priv);
-
- if (ret) {
- lbs_deb_11d("error setting domain info\n");
- goto done;
- }
- }
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function generates 11D info from user specified regioncode and download to FW
- * @param priv pointer to struct lbs_private
- * @return 0; -1
- */
-int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv)
-{
- int ret;
- struct region_channel *region_chan;
- u8 j;
-
- lbs_deb_enter(LBS_DEB_11D);
- lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band);
-
- if (priv->enable11d) {
- /* update parsed_region_chan_11; dnld domaininf to FW */
-
- for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) {
- region_chan = &priv->region_channel[j];
-
- lbs_deb_11d("%d region_chan->band %d\n", j,
- region_chan->band);
-
- if (!region_chan || !region_chan->valid
- || !region_chan->CFP)
- continue;
- if (region_chan->band != priv->curbssparams.band)
- continue;
- break;
- }
-
- if (j >= ARRAY_SIZE(priv->region_channel)) {
- lbs_deb_11d("region_chan not found, band %d\n",
- priv->curbssparams.band);
- ret = -1;
- goto done;
- }
-
- memset(&priv->parsed_region_chan, 0,
- sizeof(struct parsed_region_chan_11d));
- lbs_generate_parsed_region_chan_11d(region_chan,
- &priv->
- parsed_region_chan);
-
- memset(&priv->domainreg, 0,
- sizeof(struct lbs_802_11d_domain_reg));
- generate_domain_info_11d(&priv->parsed_region_chan,
- &priv->domainreg);
-
- ret = set_domain_info_11d(priv);
-
- if (ret) {
- lbs_deb_11d("error setting domain info\n");
- goto done;
- }
-
- }
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
- return ret;
-}
+++ /dev/null
-/**
- * This header file contains data structures and
- * function declarations of 802.11d
- */
-#ifndef _LBS_11D_
-#define _LBS_11D_
-
-#include "types.h"
-#include "defs.h"
-
-#define UNIVERSAL_REGION_CODE 0xff
-
-/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr)
- */
-#define MRVDRV_MAX_SUBBAND_802_11D 83
-
-#define COUNTRY_CODE_LEN 3
-#define MAX_NO_OF_CHAN 40
-
-struct cmd_ds_command;
-
-/** Data structure for Country IE*/
-struct ieeetypes_subbandset {
- u8 firstchan;
- u8 nrchan;
- u8 maxtxpwr;
-} __attribute__ ((packed));
-
-struct ieeetypes_countryinfoset {
- u8 element_id;
- u8 len;
- u8 countrycode[COUNTRY_CODE_LEN];
- struct ieeetypes_subbandset subband[1];
-};
-
-struct ieeetypes_countryinfofullset {
- u8 element_id;
- u8 len;
- u8 countrycode[COUNTRY_CODE_LEN];
- struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
-} __attribute__ ((packed));
-
-struct mrvlietypes_domainparamset {
- struct mrvlietypesheader header;
- u8 countrycode[COUNTRY_CODE_LEN];
- struct ieeetypes_subbandset subband[1];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11d_domain_info {
- __le16 action;
- struct mrvlietypes_domainparamset domain;
-} __attribute__ ((packed));
-
-/** domain regulatory information */
-struct lbs_802_11d_domain_reg {
- /** country Code*/
- u8 countrycode[COUNTRY_CODE_LEN];
- /** No. of subband*/
- u8 nr_subband;
- struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
-};
-
-struct chan_power_11d {
- u8 chan;
- u8 pwr;
-} __attribute__ ((packed));
-
-struct parsed_region_chan_11d {
- u8 band;
- u8 region;
- s8 countrycode[COUNTRY_CODE_LEN];
- struct chan_power_11d chanpwr[MAX_NO_OF_CHAN];
- u8 nr_chan;
-} __attribute__ ((packed));
-
-struct region_code_mapping {
- u8 region[COUNTRY_CODE_LEN];
- u8 code;
-};
-
-struct lbs_private;
-
-u8 lbs_get_scan_type_11d(u8 chan,
- struct parsed_region_chan_11d *parsed_region_chan);
-
-u32 lbs_chan_2_freq(u8 chan);
-
-void lbs_init_11d(struct lbs_private *priv);
-
-int lbs_set_universaltable(struct lbs_private *priv, u8 band);
-
-int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
- struct cmd_ds_command *cmd, u16 cmdno,
- u16 cmdOption);
-
-int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
-
-struct bss_descriptor;
-int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
- struct bss_descriptor * bss);
-
-int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv);
-
-#endif
+++ /dev/null
- Copyright (c) 2003-2006, Marvell International Ltd.
- All Rights Reserved
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc., 59
- Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
+++ /dev/null
-libertas-objs := main.o wext.o \
- rx.o tx.o cmd.o \
- cmdresp.o scan.o \
- 11d.o \
- debugfs.o \
- ethtool.o assoc.o ioctl.o
-
-usb8xxx-objs += if_usb.o
-libertas_cs-objs += if_cs.o
-libertas_sdio-objs += if_sdio.o
-
-obj-$(CONFIG_LIBERTAS) += libertas.o
-obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
-obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o
-obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
+++ /dev/null
-================================================================================
- README for USB8388
-
- (c) Copyright © 2003-2006, Marvell International Ltd.
- All Rights Reserved
-
- This software file (the "File") is distributed by Marvell International
- Ltd. under the terms of the GNU General Public License Version 2, June 1991
- (the "License"). You may use, redistribute and/or modify this File in
- accordance with the terms and conditions of the License, a copy of which
- is available along with the File in the license.txt file or by writing to
- the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-
- THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
- IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
- ARE EXPRESSLY DISCLAIMED. The License provides additional details about
- this warranty disclaimer.
-================================================================================
-
-=====================
-DRIVER LOADING
-=====================
-
- o. Copy the firmware image (e.g. usb8388.bin) to /lib/firmware/
-
- o. Load driver by using the following command:
-
- insmod usb8388.ko [fw_name=usb8388.bin]
-
-=====================
-IWPRIV COMMAND
-=====================
-
-NAME
- This manual describes the usage of private commands used in Marvell WLAN
- Linux Driver. All the commands available in Wlanconfig will not be available
- in the iwpriv.
-
-SYNOPSIS
- iwpriv <ethX> <command> [sub-command] ...
-
- iwpriv ethX setregioncode <n>
- iwpriv ethX getregioncode
-
-Version 5 Command:
- iwpriv ethX ledgpio <n>
-
-BT Commands:
- The blinding table (BT) contains a list of mac addresses that will be,
- by default, ignored by the firmware. It is also possible to invert this
- behavior so that we will ignore all traffic except for the portion
- coming from mac addresess in the list. It is primarily used for
- debugging and testing networks. It can be edited and inspected with
- the following commands:
-
- iwpriv ethX bt_reset
- iwpriv ethX bt_add <mac_address>
- iwpriv ethX bt_del <mac_address>
- iwpriv ethX bt_list <id>
- iwpriv ethX bt_get_invert <n>
- iwpriv ethX bt_set_invert <n>
-
-FWT Commands:
- The forwarding table (FWT) is a feature used to manage mesh network
- routing in the firmware. The FWT is essentially a routing table that
- associates a destination mac address (da) with a next hop receiver
- address (ra). The FWT can be inspected and edited with the following
- iwpriv commands, which are described in greater detail below.
- Eventually, the table will be automatically maintained by a custom
- routing protocol.
-
- NOTE: FWT commands replace the previous DFT commands. What were the DFT
- commands?, you might ask. They were an earlier API to the firmware that
- implemented a simple MAC-layer forwarding mechanism. In the unlikely
- event that you were using these commands, you must migrate to the new
- FWT commands which can be used to achieve the same functionality.
-
- iwpriv ethX fwt_add [parameters]
- iwpriv ethX fwt_del [parameters]
- iwpriv ethX fwt_lookup [parameters]
- iwpriv ethX fwt_list [parameters]
- iwpriv ethX fwt_list_route [parameters]
- iwpriv ethX fwt_list_neigh [parameters]
- iwpriv ethX fwt_reset [parameters]
- iwpriv ethX fwt_cleanup
- iwpriv ethX fwt_time
-
-MESH Commands:
-
- The MESH commands are used to configure various features of the mesh
- routing protocol. The following commands are supported:
-
- iwpriv ethX mesh_get_ttl
- iwpriv ethX mesh_set_ttl ttl
- iwpriv ethX mesh_get_bcastr rate
- iwpriv ethX mesh_set_bcastr rate
- iwpriv ethX get_rreq_delay
- iwpriv ethX set_rreq_delay delay
- iwpriv ethX get_route_exp
- iwpriv ethX set_route_exp time
- iwpriv ethX get_link_costs
- iwpriv ethX set_link_costs "cost54 cost36 cost11 cost1"
-
-DESCRIPTION
- Those commands are used to send additional commands to the Marvell WLAN
- card via the Linux device driver.
-
- The ethX parameter specifies the network device that is to be used to
- perform this command on. it could be eth0, eth1 etc.
-
-setregioncode
- This command is used to set the region code in the station.
- where value is 'region code' for various regions like
- USA FCC, Canada IC, Spain, France, Europe ETSI, Japan ...
-
- Usage:
- iwpriv ethX setregioncode 0x10: set region code to USA (0x10).
-
-getregioncode
- This command is used to get the region code information set in the
- station.
-
-ledgpio
- This command is used to set/get LEDs.
-
- iwpriv ethX ledgpio <LEDs>
- will set the corresponding LED for the GPIO Line.
-
- iwpriv ethX ledgpio
- will give u which LEDs are Enabled.
-
- Usage:
- iwpriv eth1 ledgpio 1 0 2 1 3 4
- will enable
- LED 1 -> GPIO 0
- LED 2 -> GPIO 1
- LED 3 -> GPIO 4
-
- iwpriv eth1 ledgpio
- shows LED information in the format as mentioned above.
-
- Note: LED0 is invalid
- Note: Maximum Number of LEDs are 16.
-
-bcn_control
- This command is used to enable disable beacons. This can also be used
- to set beacon interval.
-
- Usage:
- iwpriv ethX bcn_control [enable] [beacon_interval]
-
- enable: 0 to disable beacon. 1 to enable beacon.
- beacon_interval: 20 - 1000ms.
-
- Examples:
- 1. iwpriv ethX bcn_control
- Returns (x, y), where x if 1, indicates beacon is enabled, y
- beacon period.
- 2. iwpriv ethX bcn_control 0
- Turns off beacon transmission.
- 3. iwpriv ethX bcn_control 1 500
- Enable beacon with beacon interval 500ms.
-
-
-ledbhv
- Command iwpriv mshX ledbhv can be used to change default LEDs behaviors.
- A given LED behavior can be on, off or blinking. The duty/cycle can be set
- when behavior is programmed as blinking.
-
- Usage:
-
- 1. To get default LED behavior
- iwpriv mshX ledbhv <firmware state>
-
- 2. To set or change default LED behavior
- iwpriv mshX ledbhv <firmware state> <lednum> <behavior> <arg>
-
- firmware state: The following are some of the relevant states.
- 00: disconnected
- 01: firmware is scanning
- 02: firmware is connected and awake
- 03: firmware is sleeping
- 04: connected deep sleep
- 06: firmware disconnected link lost
- 07: firmware disconnected disassociated
- 09: data transfer while firmware is associated and not scanning.
- If firmware is already in this state, LED behavior does not change
- on this data transfer.
- 10: firmware idle, not scanning, not disconnected or disassociated.
-
- lednum: 1 or 2 for first and second LED.
-
- behavior: 0 for steady ON, 1 - steady off and 2- blinking.
-
- arg: It is used when behavior is 2 to set duty and cycle. It is defined as
- (duty << 4 | cycle). Here duty could be 0..4 and cycle 0..5 for 34,
- 74, 149, 298, 596, 1192 ms respectively.
-
- Examples:
-
- 1. To get default behavior for scan
- iwpriv mshX ledbhv 1
-
- 2. To get default behavior while data transfer
- iwpriv mshX ledbhv 9
-
- 3. To turn off LED 2
- iwpriv mshX ledbhv 2 2 1 0
- iwpriv mshX ledbhv 10 2 1 0
-
- 4. To enable LED 2 and blink LED 1 while data transfer.
- iwpriv mshX ledbhv 9 2 0 0
- iwpriv mshX ledbhv 9 1 2 4
-
- 5. To change duty cycle of LED 2 during data transfer
- iwpriv mshX ledbhv 9 2 2 36
-
- 6. To turn ON LED 2 when firmware is disassociated/disconnected.
- iwpriv mshX ledbhv 0 2 0 0
-
-
-fwt_add
- This command is used to insert an entry into the FWT table. The list of
- parameters must follow the following structure:
-
- iwpriv ethX fwt_add da ra [metric dir rate ssn dsn hopcount ttl expiration sleepmode snr]
-
- The parameters between brackets are optional, but they must appear in
- the order specified. For example, if you want to specify the metric,
- you must also specify the dir, ssn, and dsn but you need not specify the
- hopcount, expiration, sleepmode, or snr. Any unspecified parameters
- will be assigned the defaults specified below.
-
- The different parameters are:-
- da -- DA MAC address in the form 00:11:22:33:44:55
- ra -- RA MAC address in the form 00:11:22:33:44:55
- metric -- route metric (cost: smaller-metric routes are
- preferred, default is 0)
- dir -- direction (1 for direct, 0 for reverse,
- default is 1)
- rate -- data rate used for transmission to the RA,
- as specified for the rateadapt command,
- default is 3 (11Mbps)
- ssn -- Source Sequence Number (time at the RA for
- reverse routes. Default is 0)
- dsn -- Destination Sequence Number (time at the DA
- for direct routes. Default is 0)
- hopcount -- hop count (currently unused, default is 0)
- ttl -- TTL (Only used in reverse entries)
- expiration -- entry expiration (in ticks, where a tick is
- 1024us, or ~ 1ms. Use 0 for an indefinite
- entry, default is 0)
- sleepmode -- RA's sleep mode (currently unused, default is
- 0)
- snr -- SNR in the link to RA (currently unused,
- default is 0)
-
- The command does not return anything.
-
-fwt_del
- This command is used to remove an entry to the FWT table. The list of
- parameters must follow the following structure:
-
- iwpriv ethX fwt_del da ra [dir]
-
- where the different parameters are:-
- da -- DA MAC address (in the form "00:11:22:33:44:55")
- ra -- RA MAC address (in the form "00:11:22:33:44:55")
- dir -- direction (1 for direct, 0 for reverse,
- default is 1)
-
- The command does not return anything.
-
-fwt_lookup
- This command is used to get the best route in the FWT table to a given
- host. The only parameter is the MAC address of the host that is being
- looked for.
-
- iwpriv ethX fwt_lookup da
-
- where:-
- da -- DA MAC address (in the form "00:11:22:33:44:55")
-
- The command returns an output string identical to the one returned by
- fwt_list described below.
-
-
-fwt_list
- This command is used to list a route from the FWT table. The only
- parameter is the index into the table. If you want to list all the
- routes in a table, start with index=0, and keep listing until you get a
- "(null)" string. Note that the indicies may change as the fwt is
- updated. It is expected that most users will not use fwt_list directly,
- but that a utility similar to the traditional route command will be used
- to invoke fwt_list over and over.
-
- iwpriv ethX fwt_list index
-
- The output is a string of the following form:
-
- da ra valid metric dir rate ssn dsn hopcount ttl expiration
- sleepmode snr precursor
-
- where the different fields are:-
- da -- DA MAC address (in the form "00:11:22:33:44:55")
- ra -- RA MAC address (in the form "00:11:22:33:44:55")
- valid -- whether the route is valid (0 if not valid)
- metric -- route metric (cost: smaller-metric routes are preferred)
- dir -- direction (1 for direct, 0 for reverse)
- rate -- data rate used for transmission to the RA,
- as specified for the rateadapt command
- ssn -- Source Sequence Number (time at the RA for reverse routes)
- dsn -- Destination Sequence Number (time at the DA for direct routes)
- hopcount -- hop count (currently unused)
- ttl -- TTL (only used in reverse entries)
- expiration -- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry)
- sleepmode -- RA's sleep mode (currently unused)
- snr -- SNR in the link to RA (currently unused)
- precursor -- predecessor in direct routes
-
-fwt_list_route
- This command is equivalent to fwt_list.
-
-fwt_list_neigh
- This command is used to list a neighbor from the FWT table. The only
- parameter is the neighbor ID. If you want to list all the neighbors in a
- table, start with nid=0, and keep incrementing nid until you get a
- "(null)" string. Note that the nid from a fwt_list_route command can be
- used as an input to this command. Also note that this command is meant
- mostly for debugging. It is expected that users will use fwt_lookup.
- One important reason for this is that the neighbor id may change as the
- neighbor table is altered.
-
- iwpriv ethX fwt_list_neigh nid
-
- The output is a string of the following form:
-
- ra sleepmode snr references
-
- where the different fields are:-
- ra -- RA MAC address (in the form "00:11:22:33:44:55")
- sleepmode -- RA's sleep mode (currently unused)
- snr -- SNR in the link to RA (currently unused)
- references -- RA's reference counter
-
-fwt_reset
- This command is used to reset the FWT table, getting rid of all the
- entries. There are no input parameters.
-
- iwpriv ethX fwt_reset
-
- The command does not return anything.
-
-fwt_cleanup
- This command is used to perform user-based garbage recollection. The
- FWT table is checked, and all the entries that are expired or invalid
- are cleaned. Note that this is exported to the driver for debugging
- purposes, as garbage collection is also fired by the firmware when in
- space problems. There are no input parameters.
-
- iwpriv ethX fwt_cleanup
-
- The command does returns the number of invalid/expired routes deleted.
-
-fwt_time
- This command returns a card's internal time representation. It is this
- time that is used to represent the expiration times of FWT entries. The
- number is not consistent from card to card; it is simply a timer count.
- The fwt_time command is used to inspect the timer so that expiration
- times reported by fwt_list can be properly interpreted.
-
- iwpriv ethX fwt_time
-
-mesh_get_ttl
-
- The mesh ttl is the number of hops a mesh packet can traverse before it
- is dropped. This parameter is used to prevent infinite loops in the
- mesh network. The value returned by this function is the ttl assigned
- to all mesh packets. Currently there is no way to control the ttl on a
- per packet or per socket basis.
-
- iwpriv ethX mesh_get_ttl
-
-mesh_set_ttl ttl
-
- Set the ttl. The argument must be between 0 and 255.
-
- iwpriv ethX mesh_set_ttl <ttl>
-
-mesh_get_bcastr
-
- Shows the rate index used for mesh broadcast and multicast packets.
- Rates are expressed in 2 * Mb/s, ie 11Mb/s is 22, 5.5Mb/s is 11, etc.
-
- iwpriv ethX mesh_get_bcastr rate
-
-mesh_set_bcastr rate
-
- Sets the rate index for mesh broadcast and muticast packets. Rates are
- expressed in expressed in 2 * Mb/s, ie 11Mb/s is 22, 5.5Mb/s is 11, etc.
-
- iwpriv ethX mesh_set_bcastr rate
-
-get_rreq_delay
-
- Shows the delay to forward a RREQ frame. This delay allows the node to
- forward just the best route in case the same RREQ arrives to the node
- through different routes. The argument is shown in 1/100 seconds.
-
- iwpriv ethX get_rreq_delay
-
-set_rreq_delay delay
-
- Sets the RREQ forward delay. The delay is interpreted as 1/100 seconds.
-
- iwpriv ethX set_rreq_delay delay
-
-get_route_exp
-
- Shows the mesh route expiration time, in seconds.
-
- iwpriv ethX get_route_exp
-
-set_route_exp time
-
- Gets the mesh route, expiration time, in seconds.
-
- iwpriv ethX set_route_exp time
-
-get_link_costs
-
- Gets the mesh hop base cost for each used rate. The output gives us the
- base cost for hops at 54Mbps, 36Mbps, 11Mbps and 1Mbps, in that order.
- The base cost gets divided by a battery state factor to get the actual
- cost. A cost of 0 means that rate is deactivated.
-
- iwpriv ethX get_link_costs
-
-set_link_costs "cost54 cost36 cost11 cost1"
-
- Sets the mesh hop base cost for the used speeds. The input parameter
- will specify the cost for hops at 54Mbps, 36Mbps, 11Mbps and 1Mbps, in
- that order. A cost of 0 will disable a specific rate.
-
- iwpriv ethX set_link_costs "cost54 cost36 cost11 cost1"
-
-=========================
-ETHTOOL
-=========================
-
-
-Use the -i option to retrieve version information from the driver.
-
-# ethtool -i eth0
-driver: libertas
-version: COMM-USB8388-318.p4
-firmware-version: 5.110.7
-bus-info:
-
-Use the -e option to read the EEPROM contents of the card.
-
- Usage:
- ethtool -e ethX [raw on|off] [offset N] [length N]
-
- -e retrieves and prints an EEPROM dump for the specified ethernet
- device. When raw is enabled, then it dumps the raw EEPROM data
- to stdout. The length and offset parameters allow dumping cer-
- tain portions of the EEPROM. Default is to dump the entire EEP-
- ROM.
-
-# ethtool -e eth0 offset 0 length 16
-Offset Values
------- ------
-0x0000 38 33 30 58 00 00 34 f4 00 00 10 00 00 c4 17 00
-
-========================
-DEBUGFS COMMANDS
-========================
-
-those commands are used via debugfs interface
-
-===========
-rdmac
-rdbbp
-rdrf
- These commands are used to read the MAC, BBP and RF registers from the
- card. These commands take one parameter that specifies the offset
- location that is to be read. This parameter must be specified in
- hexadecimal (its possible to preceed preceding the number with a "0x").
-
- Path: /debugfs/libertas_wireless/ethX/registers/
-
- Usage:
- echo "0xa123" > rdmac ; cat rdmac
- echo "0xa123" > rdbbp ; cat rdbbp
- echo "0xa123" > rdrf ; cat rdrf
-wrmac
-wrbbp
-wrrf
- These commands are used to write the MAC, BBP and RF registers in the
- card. These commands take two parameters that specify the offset
- location and the value that is to be written. This parameters must
- be specified in hexadecimal (its possible to preceed the number
- with a "0x").
-
- Usage:
- echo "0xa123 0xaa" > wrmac
- echo "0xa123 0xaa" > wrbbp
- echo "0xa123 0xaa" > wrrf
-
-sleepparams
- This command is used to set the sleepclock configurations
-
- Path: /debugfs/libertas_wireless/ethX/
-
- Usage:
- cat sleepparams: reads the current sleepclock configuration
-
- echo "p1 p2 p3 p4 p5 p6" > sleepparams: writes the sleepclock configuration.
-
- where:
- p1 is Sleep clock error in ppm (0-65535)
- p2 is Wakeup offset in usec (0-65535)
- p3 is Clock stabilization time in usec (0-65535)
- p4 is Control periodic calibration (0-2)
- p5 is Control the use of external sleep clock (0-2)
- p6 is reserved for debug (0-65535)
-
-subscribed_events
-
- The subscribed_events directory contains the interface for the
- subscribed events API.
-
- Path: /debugfs/libertas_wireless/ethX/subscribed_events/
-
- Each event is represented by a filename. Each filename consists of the
- following three fields:
- Value Frequency Subscribed
-
- To read the current values for a given event, do:
- cat event
- To set the current values, do:
- echo "60 2 1" > event
-
- Frequency field specifies the reporting frequency for this event.
- If it is set to 0, then the event is reported only once, and then
- automatically unsubscribed. If it is set to 1, then the event is
- reported every time it occurs. If it is set to N, then the event is
- reported every Nth time it occurs.
-
- beacon_missed
- Value field specifies the number of consecutive missing beacons which
- triggers the LINK_LOSS event. This event is generated only once after
- which the firmware resets its state. At initialization, the LINK_LOSS
- event is subscribed by default. The default value of MissedBeacons is
- 60.
-
- failure_count
- Value field specifies the consecutive failure count threshold which
- triggers the generation of the MAX_FAIL event. Once this event is
- generated, the consecutive failure count is reset to 0.
- At initialization, the MAX_FAIL event is NOT subscribed by
- default.
-
- high_rssi
- This event is generated when the average received RSSI in beacons goes
- above a threshold, specified by Value.
-
- low_rssi
- This event is generated when the average received RSSI in beacons goes
- below a threshold, specified by Value.
-
- high_snr
- This event is generated when the average received SNR in beacons goes
- above a threshold, specified by Value.
-
- low_snr
- This event is generated when the average received SNR in beacons goes
- below a threshold, specified by Value.
-
-extscan
- This command is used to do a specific scan.
-
- Path: /debugfs/libertas_wireless/ethX/
-
- Usage: echo "SSID" > extscan
-
- Example:
- echo "LINKSYS-AP" > extscan
-
- To see the results of use getscantable command.
-
-getscantable
-
- Display the current contents of the driver scan table (ie. get the
- scan results).
-
- Path: /debugfs/libertas_wireless/ethX/
-
- Usage:
- cat getscantable
-
-setuserscan
- Initiate a customized scan and retrieve the results
-
-
- Path: /debugfs/libertas_wireless/ethX/
-
- Usage:
- echo "[ARGS]" > setuserscan
-
- where [ARGS]:
-
- bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan
- ssid="[SSID]" specify a SSID filter for the scan
- keep=[0 or 1] keep the previous scan results (1), discard (0)
- dur=[scan time] time to scan for each channel in milliseconds
- type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any)
-
- Any combination of the above arguments can be supplied on the command
- line. If dur tokens are absent, the driver default setting will be used.
- The bssid and ssid fields, if blank, will produce an unfiltered scan.
- The type field will default to 3 (Any) and the keep field will default
- to 0 (Discard).
-
- Examples:
- 1) Perform a passive scan on all channels for 20 ms per channel:
- echo "dur=20" > setuserscan
-
- 2) Perform an active scan for a specific SSID:
- echo "ssid="TestAP"" > setuserscan
-
- 3) Scan all available channels (B/G, A bands) for a specific BSSID, keep
- the current scan table intact, update existing or append new scan data:
- echo "bssid=00:50:43:20:12:82 keep=1" > setuserscan
-
- 4) Scan for all infrastructure networks.
- Keep the previous scan table intact. Update any duplicate BSSID/SSID
- matches with the new scan data:
- echo "type=1 keep=1" > setuserscan
-
- All entries in the scan table (not just the new scan data when keep=1)
- will be displayed upon completion by use of the getscantable ioctl.
-
-==============================================================================
+++ /dev/null
-/* Copyright (C) 2006, Red Hat, Inc. */
-
-#include <linux/etherdevice.h>
-
-#include "assoc.h"
-#include "decl.h"
-#include "host.h"
-#include "scan.h"
-#include "cmd.h"
-
-
-static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
- { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-/* The firmware needs certain bits masked out of the beacon-derviced capability
- * field when associating/joining to BSSs.
- */
-#define CAPINFO_MASK (~(0xda00))
-
-
-
-/**
- * @brief Associate to a specific BSS discovered in a scan
- *
- * @param priv A pointer to struct lbs_private structure
- * @param pbssdesc Pointer to the BSS descriptor to associate with.
- *
- * @return 0-success, otherwise fail
- */
-static int lbs_associate(struct lbs_private *priv,
- struct assoc_request *assoc_req)
-{
- int ret;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
- 0, CMD_OPTION_WAITFORRSP,
- 0, assoc_req->bss.bssid);
-
- if (ret)
- goto done;
-
- /* set preamble to firmware */
- if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
- (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- else
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-
- lbs_set_radio_control(priv);
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
-
-done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Join an adhoc network found in a previous scan
- *
- * @param priv A pointer to struct lbs_private structure
- * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
- * to attempt to join
- *
- * @return 0--success, -1--fail
- */
-static int lbs_join_adhoc_network(struct lbs_private *priv,
- struct assoc_request *assoc_req)
-{
- struct bss_descriptor *bss = &assoc_req->bss;
- int ret = 0;
-
- lbs_deb_join("current SSID '%s', ssid length %u\n",
- escape_essid(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len),
- priv->curbssparams.ssid_len);
- lbs_deb_join("requested ssid '%s', ssid length %u\n",
- escape_essid(bss->ssid, bss->ssid_len),
- bss->ssid_len);
-
- /* check if the requested SSID is already joined */
- if (priv->curbssparams.ssid_len &&
- !lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
- bss->ssid, bss->ssid_len) &&
- (priv->mode == IW_MODE_ADHOC) &&
- (priv->connect_status == LBS_CONNECTED)) {
- union iwreq_data wrqu;
-
- lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
- "current, not attempting to re-join");
-
- /* Send the re-association event though, because the association
- * request really was successful, even if just a null-op.
- */
- memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
- ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
- goto out;
- }
-
- /* Use shortpreamble only when both creator and card supports
- short preamble */
- if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) ||
- !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
- lbs_deb_join("AdhocJoin: Long preamble\n");
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
- } else {
- lbs_deb_join("AdhocJoin: Short preamble\n");
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- }
-
- lbs_set_radio_control(priv);
-
- lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
- lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
-
- priv->adhoccreate = 0;
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
- 0, CMD_OPTION_WAITFORRSP,
- OID_802_11_SSID, assoc_req);
-
-out:
- return ret;
-}
-
-/**
- * @brief Start an Adhoc Network
- *
- * @param priv A pointer to struct lbs_private structure
- * @param adhocssid The ssid of the Adhoc Network
- * @return 0--success, -1--fail
- */
-static int lbs_start_adhoc_network(struct lbs_private *priv,
- struct assoc_request *assoc_req)
-{
- int ret = 0;
-
- priv->adhoccreate = 1;
-
- if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
- lbs_deb_join("AdhocStart: Short preamble\n");
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- } else {
- lbs_deb_join("AdhocStart: Long preamble\n");
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
- }
-
- lbs_set_radio_control(priv);
-
- lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
- lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
-
- return ret;
-}
-
-int lbs_stop_adhoc_network(struct lbs_private *priv)
-{
- return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-}
-
-static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
- struct bss_descriptor *match_bss)
-{
- if (!secinfo->wep_enabled && !secinfo->WPAenabled
- && !secinfo->WPA2enabled
- && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
- && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
- && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
- return 1;
- else
- return 0;
-}
-
-static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
- struct bss_descriptor *match_bss)
-{
- if (secinfo->wep_enabled && !secinfo->WPAenabled
- && !secinfo->WPA2enabled
- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
- return 1;
- else
- return 0;
-}
-
-static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
- struct bss_descriptor *match_bss)
-{
- if (!secinfo->wep_enabled && secinfo->WPAenabled
- && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
- )
- return 1;
- else
- return 0;
-}
-
-static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
- struct bss_descriptor *match_bss)
-{
- if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
- (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
- (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
- )
- return 1;
- else
- return 0;
-}
-
-static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
- struct bss_descriptor *match_bss)
-{
- if (!secinfo->wep_enabled && !secinfo->WPAenabled
- && !secinfo->WPA2enabled
- && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
- && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
- return 1;
- else
- return 0;
-}
-
-/**
- * @brief Check if a scanned network compatible with the driver settings
- *
- * WEP WPA WPA2 ad-hoc encrypt Network
- * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
- * 0 0 0 0 NONE 0 0 0 yes No security
- * 1 0 0 0 NONE 1 0 0 yes Static WEP
- * 0 1 0 0 x 1x 1 x yes WPA
- * 0 0 1 0 x 1x x 1 yes WPA2
- * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
- * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
- *
- *
- * @param priv A pointer to struct lbs_private
- * @param index Index in scantable to check against current driver settings
- * @param mode Network mode: Infrastructure or IBSS
- *
- * @return Index in scantable, or error code if negative
- */
-static int is_network_compatible(struct lbs_private *priv,
- struct bss_descriptor *bss, uint8_t mode)
-{
- int matched = 0;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- if (bss->mode != mode)
- goto done;
-
- matched = match_bss_no_security(&priv->secinfo, bss);
- if (matched)
- goto done;
- matched = match_bss_static_wep(&priv->secinfo, bss);
- if (matched)
- goto done;
- matched = match_bss_wpa(&priv->secinfo, bss);
- if (matched) {
- lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
- "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
- priv->secinfo.wep_enabled ? "e" : "d",
- priv->secinfo.WPAenabled ? "e" : "d",
- priv->secinfo.WPA2enabled ? "e" : "d",
- (bss->capability & WLAN_CAPABILITY_PRIVACY));
- goto done;
- }
- matched = match_bss_wpa2(&priv->secinfo, bss);
- if (matched) {
- lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
- "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
- priv->secinfo.wep_enabled ? "e" : "d",
- priv->secinfo.WPAenabled ? "e" : "d",
- priv->secinfo.WPA2enabled ? "e" : "d",
- (bss->capability & WLAN_CAPABILITY_PRIVACY));
- goto done;
- }
- matched = match_bss_dynamic_wep(&priv->secinfo, bss);
- if (matched) {
- lbs_deb_scan("is_network_compatible() dynamic WEP: "
- "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
- bss->wpa_ie[0], bss->rsn_ie[0],
- (bss->capability & WLAN_CAPABILITY_PRIVACY));
- goto done;
- }
-
- /* bss security settings don't match those configured on card */
- lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
- bss->wpa_ie[0], bss->rsn_ie[0],
- priv->secinfo.wep_enabled ? "e" : "d",
- priv->secinfo.WPAenabled ? "e" : "d",
- priv->secinfo.WPA2enabled ? "e" : "d",
- (bss->capability & WLAN_CAPABILITY_PRIVACY));
-
-done:
- lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
- return matched;
-}
-
-/**
- * @brief This function finds a specific compatible BSSID in the scan list
- *
- * Used in association code
- *
- * @param priv A pointer to struct lbs_private
- * @param bssid BSSID to find in the scan list
- * @param mode Network mode: Infrastructure or IBSS
- *
- * @return index in BSSID list, or error return code (< 0)
- */
-static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
- uint8_t *bssid, uint8_t mode)
-{
- struct bss_descriptor *iter_bss;
- struct bss_descriptor *found_bss = NULL;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- if (!bssid)
- goto out;
-
- lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
-
- /* Look through the scan table for a compatible match. The loop will
- * continue past a matched bssid that is not compatible in case there
- * is an AP with multiple SSIDs assigned to the same BSSID
- */
- mutex_lock(&priv->lock);
- list_for_each_entry(iter_bss, &priv->network_list, list) {
- if (compare_ether_addr(iter_bss->bssid, bssid))
- continue; /* bssid doesn't match */
- switch (mode) {
- case IW_MODE_INFRA:
- case IW_MODE_ADHOC:
- if (!is_network_compatible(priv, iter_bss, mode))
- break;
- found_bss = iter_bss;
- break;
- default:
- found_bss = iter_bss;
- break;
- }
- }
- mutex_unlock(&priv->lock);
-
-out:
- lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
- return found_bss;
-}
-
-/**
- * @brief This function finds ssid in ssid list.
- *
- * Used in association code
- *
- * @param priv A pointer to struct lbs_private
- * @param ssid SSID to find in the list
- * @param bssid BSSID to qualify the SSID selection (if provided)
- * @param mode Network mode: Infrastructure or IBSS
- *
- * @return index in BSSID list
- */
-static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
- uint8_t *ssid, uint8_t ssid_len,
- uint8_t *bssid, uint8_t mode,
- int channel)
-{
- u32 bestrssi = 0;
- struct bss_descriptor *iter_bss = NULL;
- struct bss_descriptor *found_bss = NULL;
- struct bss_descriptor *tmp_oldest = NULL;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- mutex_lock(&priv->lock);
-
- list_for_each_entry(iter_bss, &priv->network_list, list) {
- if (!tmp_oldest ||
- (iter_bss->last_scanned < tmp_oldest->last_scanned))
- tmp_oldest = iter_bss;
-
- if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
- ssid, ssid_len) != 0)
- continue; /* ssid doesn't match */
- if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
- continue; /* bssid doesn't match */
- if ((channel > 0) && (iter_bss->channel != channel))
- continue; /* channel doesn't match */
-
- switch (mode) {
- case IW_MODE_INFRA:
- case IW_MODE_ADHOC:
- if (!is_network_compatible(priv, iter_bss, mode))
- break;
-
- if (bssid) {
- /* Found requested BSSID */
- found_bss = iter_bss;
- goto out;
- }
-
- if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
- bestrssi = SCAN_RSSI(iter_bss->rssi);
- found_bss = iter_bss;
- }
- break;
- case IW_MODE_AUTO:
- default:
- if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
- bestrssi = SCAN_RSSI(iter_bss->rssi);
- found_bss = iter_bss;
- }
- break;
- }
- }
-
-out:
- mutex_unlock(&priv->lock);
- lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
- return found_bss;
-}
-
-static int assoc_helper_essid(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
- struct bss_descriptor * bss;
- int channel = -1;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- /* FIXME: take channel into account when picking SSIDs if a channel
- * is set.
- */
-
- if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
- channel = assoc_req->channel;
-
- lbs_deb_assoc("SSID '%s' requested\n",
- escape_essid(assoc_req->ssid, assoc_req->ssid_len));
- if (assoc_req->mode == IW_MODE_INFRA) {
- lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
- assoc_req->ssid_len);
-
- bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
- assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
- if (bss != NULL) {
- memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
- ret = lbs_associate(priv, assoc_req);
- } else {
- lbs_deb_assoc("SSID not found; cannot associate\n");
- }
- } else if (assoc_req->mode == IW_MODE_ADHOC) {
- /* Scan for the network, do not save previous results. Stale
- * scan data will cause us to join a non-existant adhoc network
- */
- lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
- assoc_req->ssid_len);
-
- /* Search for the requested SSID in the scan table */
- bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
- assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
- if (bss != NULL) {
- lbs_deb_assoc("SSID found, will join\n");
- memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
- lbs_join_adhoc_network(priv, assoc_req);
- } else {
- /* else send START command */
- lbs_deb_assoc("SSID not found, creating adhoc network\n");
- memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
- IW_ESSID_MAX_SIZE);
- assoc_req->bss.ssid_len = assoc_req->ssid_len;
- lbs_start_adhoc_network(priv, assoc_req);
- }
- }
-
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int assoc_helper_bssid(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
- struct bss_descriptor * bss;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %s",
- print_mac(mac, assoc_req->bssid));
-
- /* Search for index position in list for requested MAC */
- bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
- assoc_req->mode);
- if (bss == NULL) {
- lbs_deb_assoc("ASSOC: WAP: BSSID %s not found, "
- "cannot associate.\n", print_mac(mac, assoc_req->bssid));
- goto out;
- }
-
- memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
- if (assoc_req->mode == IW_MODE_INFRA) {
- ret = lbs_associate(priv, assoc_req);
- lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
- } else if (assoc_req->mode == IW_MODE_ADHOC) {
- lbs_join_adhoc_network(priv, assoc_req);
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int assoc_helper_associate(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0, done = 0;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- /* If we're given and 'any' BSSID, try associating based on SSID */
-
- if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- if (compare_ether_addr(bssid_any, assoc_req->bssid)
- && compare_ether_addr(bssid_off, assoc_req->bssid)) {
- ret = assoc_helper_bssid(priv, assoc_req);
- done = 1;
- }
- }
-
- if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- ret = assoc_helper_essid(priv, assoc_req);
- }
-
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int assoc_helper_mode(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- if (assoc_req->mode == priv->mode)
- goto done;
-
- if (assoc_req->mode == IW_MODE_INFRA) {
- if (priv->psstate != PS_STATE_FULL_POWER)
- lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
- priv->psmode = LBS802_11POWERMODECAM;
- }
-
- priv->mode = assoc_req->mode;
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_SNMP_MIB,
- 0, CMD_OPTION_WAITFORRSP,
- OID_802_11_INFRASTRUCTURE_MODE,
- /* Shoot me now */ (void *) (size_t) assoc_req->mode);
-
-done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-static int assoc_helper_channel(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- ret = lbs_update_channel(priv);
- if (ret) {
- lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
- goto done;
- }
-
- if (assoc_req->channel == priv->curbssparams.channel)
- goto done;
-
- if (priv->mesh_dev) {
- /* Change mesh channel first; 21.p21 firmware won't let
- you change channel otherwise (even though it'll return
- an error to this */
- lbs_mesh_config(priv, 0, assoc_req->channel);
- }
-
- lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
- priv->curbssparams.channel, assoc_req->channel);
-
- ret = lbs_set_channel(priv, assoc_req->channel);
- if (ret < 0)
- lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
-
- /* FIXME: shouldn't need to grab the channel _again_ after setting
- * it since the firmware is supposed to return the new channel, but
- * whatever... */
- ret = lbs_update_channel(priv);
- if (ret) {
- lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
- goto done;
- }
-
- if (assoc_req->channel != priv->curbssparams.channel) {
- lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
- assoc_req->channel);
- goto restore_mesh;
- }
-
- if ( assoc_req->secinfo.wep_enabled
- && (assoc_req->wep_keys[0].len
- || assoc_req->wep_keys[1].len
- || assoc_req->wep_keys[2].len
- || assoc_req->wep_keys[3].len)) {
- /* Make sure WEP keys are re-sent to firmware */
- set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
- }
-
- /* Must restart/rejoin adhoc networks after channel change */
- set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
-
- restore_mesh:
- if (priv->mesh_dev)
- lbs_mesh_config(priv, 1, priv->curbssparams.channel);
-
- done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int assoc_helper_wep_keys(struct lbs_private *priv,
- struct assoc_request *assoc_req)
-{
- int i;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- /* Set or remove WEP keys */
- if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
- assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
- ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
- else
- ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
-
- if (ret)
- goto out;
-
- /* enable/disable the MAC's WEP packet filter */
- if (assoc_req->secinfo.wep_enabled)
- priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
- else
- priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
-
- lbs_set_mac_control(priv);
-
- mutex_lock(&priv->lock);
-
- /* Copy WEP keys into priv wep key fields */
- for (i = 0; i < 4; i++) {
- memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
- sizeof(struct enc_key));
- }
- priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
-
- mutex_unlock(&priv->lock);
-
-out:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-static int assoc_helper_secinfo(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
- uint16_t do_wpa;
- uint16_t rsn = 0;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- memcpy(&priv->secinfo, &assoc_req->secinfo,
- sizeof(struct lbs_802_11_security));
-
- lbs_set_mac_control(priv);
-
- /* If RSN is already enabled, don't try to enable it again, since
- * ENABLE_RSN resets internal state machines and will clobber the
- * 4-way WPA handshake.
- */
-
- /* Get RSN enabled/disabled */
- ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
- if (ret) {
- lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
- goto out;
- }
-
- /* Don't re-enable RSN if it's already enabled */
- do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
- if (do_wpa == rsn)
- goto out;
-
- /* Set RSN enabled/disabled */
- ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
-
-out:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int assoc_helper_wpa_keys(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
- unsigned int flags = assoc_req->flags;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- /* Work around older firmware bug where WPA unicast and multicast
- * keys must be set independently. Seen in SDIO parts with firmware
- * version 5.0.11p0.
- */
-
- if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
- ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
- assoc_req->flags = flags;
- }
-
- if (ret)
- goto out;
-
- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
- clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-
- ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
- assoc_req->flags = flags;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int assoc_helper_wpa_ie(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
- memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
- priv->wpa_ie_len = assoc_req->wpa_ie_len;
- } else {
- memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN);
- priv->wpa_ie_len = 0;
- }
-
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int should_deauth_infrastructure(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- int ret = 0;
-
- if (priv->connect_status != LBS_CONNECTED)
- return 0;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
- if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- lbs_deb_assoc("Deauthenticating due to new SSID\n");
- ret = 1;
- goto out;
- }
-
- if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
- if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
- lbs_deb_assoc("Deauthenticating due to new security\n");
- ret = 1;
- goto out;
- }
- }
-
- if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- lbs_deb_assoc("Deauthenticating due to new BSSID\n");
- ret = 1;
- goto out;
- }
-
- if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
- lbs_deb_assoc("Deauthenticating due to channel switch\n");
- ret = 1;
- goto out;
- }
-
- /* FIXME: deal with 'auto' mode somehow */
- if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
- if (assoc_req->mode != IW_MODE_INFRA) {
- lbs_deb_assoc("Deauthenticating due to leaving "
- "infra mode\n");
- ret = 1;
- goto out;
- }
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-
-static int should_stop_adhoc(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-{
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- if (priv->connect_status != LBS_CONNECTED)
- return 0;
-
- if (lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
- assoc_req->ssid, assoc_req->ssid_len) != 0)
- return 1;
-
- /* FIXME: deal with 'auto' mode somehow */
- if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
- if (assoc_req->mode != IW_MODE_ADHOC)
- return 1;
- }
-
- if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
- if (assoc_req->channel != priv->curbssparams.channel)
- return 1;
- }
-
- lbs_deb_leave(LBS_DEB_ASSOC);
- return 0;
-}
-
-
-/**
- * @brief This function finds the best SSID in the Scan List
- *
- * Search the scan table for the best SSID that also matches the current
- * adapter network preference (infrastructure or adhoc)
- *
- * @param priv A pointer to struct lbs_private
- *
- * @return index in BSSID list
- */
-static struct bss_descriptor *lbs_find_best_ssid_in_list(
- struct lbs_private *priv, uint8_t mode)
-{
- uint8_t bestrssi = 0;
- struct bss_descriptor *iter_bss;
- struct bss_descriptor *best_bss = NULL;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- mutex_lock(&priv->lock);
-
- list_for_each_entry(iter_bss, &priv->network_list, list) {
- switch (mode) {
- case IW_MODE_INFRA:
- case IW_MODE_ADHOC:
- if (!is_network_compatible(priv, iter_bss, mode))
- break;
- if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
- break;
- bestrssi = SCAN_RSSI(iter_bss->rssi);
- best_bss = iter_bss;
- break;
- case IW_MODE_AUTO:
- default:
- if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
- break;
- bestrssi = SCAN_RSSI(iter_bss->rssi);
- best_bss = iter_bss;
- break;
- }
- }
-
- mutex_unlock(&priv->lock);
- lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
- return best_bss;
-}
-
-/**
- * @brief Find the best AP
- *
- * Used from association worker.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param pSSID A pointer to AP's ssid
- *
- * @return 0--success, otherwise--fail
- */
-static int lbs_find_best_network_ssid(struct lbs_private *priv,
- uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
- uint8_t *out_mode)
-{
- int ret = -1;
- struct bss_descriptor *found;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- priv->scan_ssid_len = 0;
- lbs_scan_networks(priv, 1);
- if (priv->surpriseremoved)
- goto out;
-
- found = lbs_find_best_ssid_in_list(priv, preferred_mode);
- if (found && (found->ssid_len > 0)) {
- memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
- *out_ssid_len = found->ssid_len;
- *out_mode = found->mode;
- ret = 0;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
-}
-
-
-void lbs_association_worker(struct work_struct *work)
-{
- struct lbs_private *priv = container_of(work, struct lbs_private,
- assoc_work.work);
- struct assoc_request * assoc_req = NULL;
- int ret = 0;
- int find_any_ssid = 0;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- mutex_lock(&priv->lock);
- assoc_req = priv->pending_assoc_req;
- priv->pending_assoc_req = NULL;
- priv->in_progress_assoc_req = assoc_req;
- mutex_unlock(&priv->lock);
-
- if (!assoc_req)
- goto done;
-
- lbs_deb_assoc(
- "Association Request:\n"
- " flags: 0x%08lx\n"
- " SSID: '%s'\n"
- " chann: %d\n"
- " band: %d\n"
- " mode: %d\n"
- " BSSID: %s\n"
- " secinfo: %s%s%s\n"
- " auth_mode: %d\n",
- assoc_req->flags,
- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
- assoc_req->channel, assoc_req->band, assoc_req->mode,
- print_mac(mac, assoc_req->bssid),
- assoc_req->secinfo.WPAenabled ? " WPA" : "",
- assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
- assoc_req->secinfo.wep_enabled ? " WEP" : "",
- assoc_req->secinfo.auth_mode);
-
- /* If 'any' SSID was specified, find an SSID to associate with */
- if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
- && !assoc_req->ssid_len)
- find_any_ssid = 1;
-
- /* But don't use 'any' SSID if there's a valid locked BSSID to use */
- if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- if (compare_ether_addr(assoc_req->bssid, bssid_any)
- && compare_ether_addr(assoc_req->bssid, bssid_off))
- find_any_ssid = 0;
- }
-
- if (find_any_ssid) {
- u8 new_mode = assoc_req->mode;
-
- ret = lbs_find_best_network_ssid(priv, assoc_req->ssid,
- &assoc_req->ssid_len, assoc_req->mode, &new_mode);
- if (ret) {
- lbs_deb_assoc("Could not find best network\n");
- ret = -ENETUNREACH;
- goto out;
- }
-
- /* Ensure we switch to the mode of the AP */
- if (assoc_req->mode == IW_MODE_AUTO) {
- set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
- assoc_req->mode = new_mode;
- }
- }
-
- /*
- * Check if the attributes being changing require deauthentication
- * from the currently associated infrastructure access point.
- */
- if (priv->mode == IW_MODE_INFRA) {
- if (should_deauth_infrastructure(priv, assoc_req)) {
- ret = lbs_send_deauthentication(priv);
- if (ret) {
- lbs_deb_assoc("Deauthentication due to new "
- "configuration request failed: %d\n",
- ret);
- }
- }
- } else if (priv->mode == IW_MODE_ADHOC) {
- if (should_stop_adhoc(priv, assoc_req)) {
- ret = lbs_stop_adhoc_network(priv);
- if (ret) {
- lbs_deb_assoc("Teardown of AdHoc network due to "
- "new configuration request failed: %d\n",
- ret);
- }
-
- }
- }
-
- /* Send the various configuration bits to the firmware */
- if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
- ret = assoc_helper_mode(priv, assoc_req);
- if (ret)
- goto out;
- }
-
- if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
- ret = assoc_helper_channel(priv, assoc_req);
- if (ret)
- goto out;
- }
-
- if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
- || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
- ret = assoc_helper_wep_keys(priv, assoc_req);
- if (ret)
- goto out;
- }
-
- if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
- ret = assoc_helper_secinfo(priv, assoc_req);
- if (ret)
- goto out;
- }
-
- if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
- ret = assoc_helper_wpa_ie(priv, assoc_req);
- if (ret)
- goto out;
- }
-
- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
- || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- ret = assoc_helper_wpa_keys(priv, assoc_req);
- if (ret)
- goto out;
- }
-
- /* SSID/BSSID should be the _last_ config option set, because they
- * trigger the association attempt.
- */
- if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)
- || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- int success = 1;
-
- ret = assoc_helper_associate(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC: association unsuccessful: %d\n",
- ret);
- success = 0;
- }
-
- if (priv->connect_status != LBS_CONNECTED) {
- lbs_deb_assoc("ASSOC: association unsuccessful, "
- "not connected\n");
- success = 0;
- }
-
- if (success) {
- lbs_deb_assoc("associated to %s\n",
- print_mac(mac, priv->curbssparams.bssid));
- lbs_prepare_and_send_command(priv,
- CMD_802_11_RSSI,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
- } else {
- ret = -1;
- }
- }
-
-out:
- if (ret) {
- lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
- ret);
- }
-
- mutex_lock(&priv->lock);
- priv->in_progress_assoc_req = NULL;
- mutex_unlock(&priv->lock);
- kfree(assoc_req);
-
-done:
- lbs_deb_leave(LBS_DEB_ASSOC);
-}
-
-
-/*
- * Caller MUST hold any necessary locks
- */
-struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
-{
- struct assoc_request * assoc_req;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
- if (!priv->pending_assoc_req) {
- priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
- GFP_KERNEL);
- if (!priv->pending_assoc_req) {
- lbs_pr_info("Not enough memory to allocate association"
- " request!\n");
- return NULL;
- }
- }
-
- /* Copy current configuration attributes to the association request,
- * but don't overwrite any that are already set.
- */
- assoc_req = priv->pending_assoc_req;
- if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
- IW_ESSID_MAX_SIZE);
- assoc_req->ssid_len = priv->curbssparams.ssid_len;
- }
-
- if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
- assoc_req->channel = priv->curbssparams.channel;
-
- if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
- assoc_req->band = priv->curbssparams.band;
-
- if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
- assoc_req->mode = priv->mode;
-
- if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- memcpy(&assoc_req->bssid, priv->curbssparams.bssid,
- ETH_ALEN);
- }
-
- if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
- int i;
- for (i = 0; i < 4; i++) {
- memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i],
- sizeof(struct enc_key));
- }
- }
-
- if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
- assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
-
- if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
- sizeof(struct enc_key));
- }
-
- if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
- sizeof(struct enc_key));
- }
-
- if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
- memcpy(&assoc_req->secinfo, &priv->secinfo,
- sizeof(struct lbs_802_11_security));
- }
-
- if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_ie, &priv->wpa_ie,
- MAX_WPA_IE_LEN);
- assoc_req->wpa_ie_len = priv->wpa_ie_len;
- }
-
- lbs_deb_leave(LBS_DEB_ASSOC);
- return assoc_req;
-}
-
-
-/**
- * @brief This function finds common rates between rate1 and card rates.
- *
- * It will fill common rates in rate1 as output if found.
- *
- * NOTE: Setting the MSB of the basic rates need to be taken
- * care, either before or after calling this function
- *
- * @param priv A pointer to struct lbs_private structure
- * @param rate1 the buffer which keeps input and output
- * @param rate1_size the size of rate1 buffer; new size of buffer on return
- *
- * @return 0 or -1
- */
-static int get_common_rates(struct lbs_private *priv,
- u8 *rates,
- u16 *rates_size)
-{
- u8 *card_rates = lbs_bg_rates;
- size_t num_card_rates = sizeof(lbs_bg_rates);
- int ret = 0, i, j;
- u8 tmp[30];
- size_t tmp_size = 0;
-
- /* For each rate in card_rates that exists in rate1, copy to tmp */
- for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
- for (j = 0; rates[j] && (j < *rates_size); j++) {
- if (rates[j] == card_rates[i])
- tmp[tmp_size++] = card_rates[i];
- }
- }
-
- lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
- lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
- lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
- lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
-
- if (!priv->auto_rate) {
- for (i = 0; i < tmp_size; i++) {
- if (tmp[i] == priv->cur_rate)
- goto done;
- }
- lbs_pr_alert("Previously set fixed data rate %#x isn't "
- "compatible with the network.\n", priv->cur_rate);
- ret = -1;
- goto done;
- }
- ret = 0;
-
-done:
- memset(rates, 0, *rates_size);
- *rates_size = min_t(int, tmp_size, *rates_size);
- memcpy(rates, tmp, *rates_size);
- return ret;
-}
-
-
-/**
- * @brief Sets the MSB on basic rates as the firmware requires
- *
- * Scan through an array and set the MSB for basic data rates.
- *
- * @param rates buffer of data rates
- * @param len size of buffer
- */
-static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- if (rates[i] == 0x02 || rates[i] == 0x04 ||
- rates[i] == 0x0b || rates[i] == 0x16)
- rates[i] |= 0x80;
- }
-}
-
-/**
- * @brief Send Deauthentication Request
- *
- * @param priv A pointer to struct lbs_private structure
- * @return 0--success, -1--fail
- */
-int lbs_send_deauthentication(struct lbs_private *priv)
-{
- return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-}
-
-/**
- * @brief This function prepares command of authenticate.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param cmd A pointer to cmd_ds_command structure
- * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
- *
- * @return 0 or -1
- */
-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf)
-{
- struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
- int ret = -1;
- u8 *bssid = pdata_buf;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
- + S_DS_GEN);
-
- /* translate auth mode to 802.11 defined wire value */
- switch (priv->secinfo.auth_mode) {
- case IW_AUTH_ALG_OPEN_SYSTEM:
- pauthenticate->authtype = 0x00;
- break;
- case IW_AUTH_ALG_SHARED_KEY:
- pauthenticate->authtype = 0x01;
- break;
- case IW_AUTH_ALG_LEAP:
- pauthenticate->authtype = 0x80;
- break;
- default:
- lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
- priv->secinfo.auth_mode);
- goto out;
- }
-
- memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
-
- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
- print_mac(mac, bssid), pauthenticate->authtype);
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd)
-{
- struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
- S_DS_GEN);
-
- /* set AP MAC address */
- memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
-
- /* Reason code 3 = Station is leaving */
-#define REASON_CODE_STA_LEAVING 3
- dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
-
-int lbs_cmd_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
- int ret = 0;
- struct assoc_request *assoc_req = pdata_buf;
- struct bss_descriptor *bss = &assoc_req->bss;
- u8 *pos;
- u16 tmpcap, tmplen;
- struct mrvlietypes_ssidparamset *ssid;
- struct mrvlietypes_phyparamset *phy;
- struct mrvlietypes_ssparamset *ss;
- struct mrvlietypes_ratesparamset *rates;
- struct mrvlietypes_rsnparamset *rsn;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- pos = (u8 *) passo;
-
- if (!priv) {
- ret = -1;
- goto done;
- }
-
- cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
-
- memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
- pos += sizeof(passo->peerstaaddr);
-
- /* set the listen interval */
- passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
-
- pos += sizeof(passo->capability);
- pos += sizeof(passo->listeninterval);
- pos += sizeof(passo->bcnperiod);
- pos += sizeof(passo->dtimperiod);
-
- ssid = (struct mrvlietypes_ssidparamset *) pos;
- ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
- tmplen = bss->ssid_len;
- ssid->header.len = cpu_to_le16(tmplen);
- memcpy(ssid->ssid, bss->ssid, tmplen);
- pos += sizeof(ssid->header) + tmplen;
-
- phy = (struct mrvlietypes_phyparamset *) pos;
- phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
- tmplen = sizeof(phy->fh_ds.dsparamset);
- phy->header.len = cpu_to_le16(tmplen);
- memcpy(&phy->fh_ds.dsparamset,
- &bss->phyparamset.dsparamset.currentchan,
- tmplen);
- pos += sizeof(phy->header) + tmplen;
-
- ss = (struct mrvlietypes_ssparamset *) pos;
- ss->header.type = cpu_to_le16(TLV_TYPE_CF);
- tmplen = sizeof(ss->cf_ibss.cfparamset);
- ss->header.len = cpu_to_le16(tmplen);
- pos += sizeof(ss->header) + tmplen;
-
- rates = (struct mrvlietypes_ratesparamset *) pos;
- rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
- memcpy(&rates->rates, &bss->rates, MAX_RATES);
- tmplen = MAX_RATES;
- if (get_common_rates(priv, rates->rates, &tmplen)) {
- ret = -1;
- goto done;
- }
- pos += sizeof(rates->header) + tmplen;
- rates->header.len = cpu_to_le16(tmplen);
- lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
-
- /* Copy the infra. association rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(rates->rates, tmplen);
-
- if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
- rsn = (struct mrvlietypes_rsnparamset *) pos;
- /* WPA_IE or WPA2_IE */
- rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
- tmplen = (u16) assoc_req->wpa_ie[1];
- rsn->header.len = cpu_to_le16(tmplen);
- memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
- lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
- sizeof(rsn->header) + tmplen);
- pos += sizeof(rsn->header) + tmplen;
- }
-
- /* update curbssparams */
- priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
-
- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
-
- /* set the capability info */
- tmpcap = (bss->capability & CAPINFO_MASK);
- if (bss->mode == IW_MODE_INFRA)
- tmpcap |= WLAN_CAPABILITY_ESS;
- passo->capability = cpu_to_le16(tmpcap);
- lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
-
-done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
- int ret = 0;
- int cmdappendsize = 0;
- struct assoc_request *assoc_req = pdata_buf;
- u16 tmpcap = 0;
- size_t ratesize = 0;
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- if (!priv) {
- ret = -1;
- goto done;
- }
-
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
-
- /*
- * Fill in the parameters for 2 data structures:
- * 1. cmd_ds_802_11_ad_hoc_start command
- * 2. priv->scantable[i]
- *
- * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
- * probe delay, and cap info.
- *
- * Firmware will fill up beacon period, DTIM, Basic rates
- * and operational rates.
- */
-
- memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
- memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
-
- lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
- assoc_req->ssid_len);
-
- /* set the BSS type */
- adhs->bsstype = CMD_BSS_TYPE_IBSS;
- priv->mode = IW_MODE_ADHOC;
- if (priv->beacon_period == 0)
- priv->beacon_period = MRVDRV_BEACON_INTERVAL;
- adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
-
- /* set Physical param set */
-#define DS_PARA_IE_ID 3
-#define DS_PARA_IE_LEN 1
-
- adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
- adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
-
- WARN_ON(!assoc_req->channel);
-
- lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
- assoc_req->channel);
-
- adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
-
- /* set IBSS param set */
-#define IBSS_PARA_IE_ID 6
-#define IBSS_PARA_IE_LEN 2
-
- adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
- adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
- adhs->ssparamset.ibssparamset.atimwindow = 0;
-
- /* set capability info */
- tmpcap = WLAN_CAPABILITY_IBSS;
- if (assoc_req->secinfo.wep_enabled) {
- lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
- "setting privacy on\n");
- tmpcap |= WLAN_CAPABILITY_PRIVACY;
- } else {
- lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
- "setting privacy off\n");
- }
- adhs->capability = cpu_to_le16(tmpcap);
-
- /* probedelay */
- adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-
- memset(adhs->rates, 0, sizeof(adhs->rates));
- ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
- memcpy(adhs->rates, lbs_bg_rates, ratesize);
-
- /* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(adhs->rates, ratesize);
-
- lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
- adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
-
- lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
-
- if (lbs_create_dnld_countryinfo_11d(priv)) {
- lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
- S_DS_GEN + cmdappendsize);
-
- ret = 0;
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
-{
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
- cmd->size = cpu_to_le16(S_DS_GEN);
-
- return 0;
-}
-
-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
- struct assoc_request *assoc_req = pdata_buf;
- struct bss_descriptor *bss = &assoc_req->bss;
- int cmdappendsize = 0;
- int ret = 0;
- u16 ratesize = 0;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
-
- join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
- join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
-
- memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
- memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
-
- memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
- sizeof(union ieeetypes_phyparamset));
-
- memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
- sizeof(union IEEEtypes_ssparamset));
-
- join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
- lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
- bss->capability, CAPINFO_MASK);
-
- /* information on BSSID descriptor passed to FW */
- lbs_deb_join(
- "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
- print_mac(mac, join_cmd->bss.bssid),
- join_cmd->bss.ssid);
-
- /* failtimeout */
- join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
-
- /* probedelay */
- join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-
- priv->curbssparams.channel = bss->channel;
-
- /* Copy Data rates from the rates recorded in scan response */
- memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
- ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
- memcpy(join_cmd->bss.rates, bss->rates, ratesize);
- if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
- lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
- ret = -1;
- goto done;
- }
-
- /* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
-
- join_cmd->bss.ssparamset.ibssparamset.atimwindow =
- cpu_to_le16(bss->atimwindow);
-
- if (assoc_req->secinfo.wep_enabled) {
- u16 tmp = le16_to_cpu(join_cmd->bss.capability);
- tmp |= WLAN_CAPABILITY_PRIVACY;
- join_cmd->bss.capability = cpu_to_le16(tmp);
- }
-
- if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
- /* wake up first */
- __le32 Localpsmode;
-
- Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_PS_MODE,
- CMD_ACT_SET,
- 0, 0, &Localpsmode);
-
- if (ret) {
- ret = -1;
- goto done;
- }
- }
-
- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
- S_DS_GEN + cmdappendsize);
-
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_ret_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- int ret = 0;
- union iwreq_data wrqu;
- struct ieeetypes_assocrsp *passocrsp;
- struct bss_descriptor *bss;
- u16 status_code;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- if (!priv->in_progress_assoc_req) {
- lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
- ret = -1;
- goto done;
- }
- bss = &priv->in_progress_assoc_req->bss;
-
- passocrsp = (struct ieeetypes_assocrsp *) &resp->params;
-
- /*
- * Older FW versions map the IEEE 802.11 Status Code in the association
- * response to the following values returned in passocrsp->statuscode:
- *
- * IEEE Status Code Marvell Status Code
- * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
- * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * others -> 0x0003 ASSOC_RESULT_REFUSED
- *
- * Other response codes:
- * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
- * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
- * association response from the AP)
- */
-
- status_code = le16_to_cpu(passocrsp->statuscode);
- switch (status_code) {
- case 0x00:
- break;
- case 0x01:
- lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
- break;
- case 0x02:
- lbs_deb_assoc("ASSOC_RESP: internal timer "
- "expired while waiting for the AP\n");
- break;
- case 0x03:
- lbs_deb_assoc("ASSOC_RESP: association "
- "refused by AP\n");
- break;
- case 0x04:
- lbs_deb_assoc("ASSOC_RESP: authentication "
- "refused by AP\n");
- break;
- default:
- lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
- " unknown\n", status_code);
- break;
- }
-
- if (status_code) {
- lbs_mac_event_disconnected(priv);
- ret = -1;
- goto done;
- }
-
- lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
- le16_to_cpu(resp->size) - S_DS_GEN);
-
- /* Send a Media Connected event, according to the Spec */
- priv->connect_status = LBS_CONNECTED;
-
- /* Update current SSID and BSSID */
- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
- priv->curbssparams.ssid_len = bss->ssid_len;
- memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
- priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
- priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
-
- memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
- memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
- priv->nextSNRNF = 0;
- priv->numSNRNF = 0;
-
- netif_carrier_on(priv->dev);
- if (!priv->tx_pending_len)
- netif_wake_queue(priv->dev);
-
- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
-done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-int lbs_ret_80211_disassociate(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_JOIN);
-
- lbs_mac_event_disconnected(priv);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
-
-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- int ret = 0;
- u16 command = le16_to_cpu(resp->command);
- u16 result = le16_to_cpu(resp->result);
- struct cmd_ds_802_11_ad_hoc_result *padhocresult;
- union iwreq_data wrqu;
- struct bss_descriptor *bss;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- padhocresult = &resp->params.result;
-
- lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
- lbs_deb_join("ADHOC_RESP: command = %x\n", command);
- lbs_deb_join("ADHOC_RESP: result = %x\n", result);
-
- if (!priv->in_progress_assoc_req) {
- lbs_deb_join("ADHOC_RESP: no in-progress association "
- "request\n");
- ret = -1;
- goto done;
- }
- bss = &priv->in_progress_assoc_req->bss;
-
- /*
- * Join result code 0 --> SUCCESS
- */
- if (result) {
- lbs_deb_join("ADHOC_RESP: failed\n");
- if (priv->connect_status == LBS_CONNECTED)
- lbs_mac_event_disconnected(priv);
- ret = -1;
- goto done;
- }
-
- /*
- * Now the join cmd should be successful
- * If BSSID has changed use SSID to compare instead of BSSID
- */
- lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
- escape_essid(bss->ssid, bss->ssid_len));
-
- /* Send a Media Connected event, according to the Spec */
- priv->connect_status = LBS_CONNECTED;
-
- if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
- /* Update the created network descriptor with the new BSSID */
- memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
- }
-
- /* Set the BSSID from the joined/started descriptor */
- memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
- /* Set the new SSID to current SSID */
- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
- priv->curbssparams.ssid_len = bss->ssid_len;
-
- netif_carrier_on(priv->dev);
- if (!priv->tx_pending_len)
- netif_wake_queue(priv->dev);
-
- memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
- lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
- lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
- lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
- print_mac(mac, padhocresult->bssid));
-
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_JOIN);
-
- lbs_mac_event_disconnected(priv);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
+++ /dev/null
-/* Copyright (C) 2006, Red Hat, Inc. */
-
-#ifndef _LBS_ASSOC_H_
-#define _LBS_ASSOC_H_
-
-#include "dev.h"
-
-void lbs_association_worker(struct work_struct *work);
-struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
-
-struct cmd_ds_command;
-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd);
-int lbs_cmd_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-
-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *resp);
-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
-int lbs_ret_80211_disassociate(struct lbs_private *priv);
-int lbs_ret_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *resp);
-
-int lbs_stop_adhoc_network(struct lbs_private *priv);
-
-int lbs_send_deauthentication(struct lbs_private *priv);
-
-#endif /* _LBS_ASSOC_H */
+++ /dev/null
-/**
- * This file contains the handling of command.
- * It prepares command and sends it to firmware when it is ready.
- */
-
-#include <net/iw_handler.h>
-#include <linux/kfifo.h>
-#include "host.h"
-#include "hostcmd.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "assoc.h"
-#include "wext.h"
-#include "cmd.h"
-
-static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
-
-
-/**
- * @brief Simple callback that copies response back into command
- *
- * @param priv A pointer to struct lbs_private structure
- * @param extra A pointer to the original command structure for which
- * 'resp' is a response
- * @param resp A pointer to the command response
- *
- * @return 0 on success, error on failure
- */
-int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
- struct cmd_header *resp)
-{
- struct cmd_header *buf = (void *)extra;
- uint16_t copy_len;
-
- copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
- memcpy(buf, resp, copy_len);
- return 0;
-}
-EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
-
-/**
- * @brief Simple callback that ignores the result. Use this if
- * you just want to send a command to the hardware, but don't
- * care for the result.
- *
- * @param priv ignored
- * @param extra ignored
- * @param resp ignored
- *
- * @return 0 for success
- */
-static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
- struct cmd_header *resp)
-{
- return 0;
-}
-
-
-/**
- * @brief Checks whether a command is allowed in Power Save mode
- *
- * @param command the command ID
- * @return 1 if allowed, 0 if not allowed
- */
-static u8 is_command_allowed_in_ps(u16 cmd)
-{
- switch (cmd) {
- case CMD_802_11_RSSI:
- return 1;
- default:
- break;
- }
- return 0;
-}
-
-/**
- * @brief Updates the hardware details like MAC address and regulatory region
- *
- * @param priv A pointer to struct lbs_private structure
- *
- * @return 0 on success, error on failure
- */
-int lbs_update_hw_spec(struct lbs_private *priv)
-{
- struct cmd_ds_get_hw_spec cmd;
- int ret = -1;
- u32 i;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
- ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
- if (ret)
- goto out;
-
- priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
-
- /* The firmware release is in an interesting format: the patch
- * level is in the most significant nibble ... so fix that: */
- priv->fwrelease = le32_to_cpu(cmd.fwrelease);
- priv->fwrelease = (priv->fwrelease << 8) |
- (priv->fwrelease >> 24 & 0xff);
-
- /* Some firmware capabilities:
- * CF card firmware 5.0.16p0: cap 0x00000303
- * USB dongle firmware 5.110.17p2: cap 0x00000303
- */
- printk("libertas: %s, fw %u.%u.%up%u, cap 0x%08x\n",
- print_mac(mac, cmd.permanentaddr),
- priv->fwrelease >> 24 & 0xff,
- priv->fwrelease >> 16 & 0xff,
- priv->fwrelease >> 8 & 0xff,
- priv->fwrelease & 0xff,
- priv->fwcapinfo);
- lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
- cmd.hwifversion, cmd.version);
-
- /* Clamp region code to 8-bit since FW spec indicates that it should
- * only ever be 8-bit, even though the field size is 16-bit. Some firmware
- * returns non-zero high 8 bits here.
- */
- priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
-
- for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
- /* use the region code to search for the index */
- if (priv->regioncode == lbs_region_code_to_index[i])
- break;
- }
-
- /* if it's unidentified region code, use the default (USA) */
- if (i >= MRVDRV_MAX_REGION_CODE) {
- priv->regioncode = 0x10;
- lbs_pr_info("unidentified region code; using the default (USA)\n");
- }
-
- if (priv->current_addr[0] == 0xff)
- memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
-
- memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
- if (priv->mesh_dev)
- memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
-
- if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
- ret = -1;
- goto out;
- }
-
- if (lbs_set_universaltable(priv, 0)) {
- ret = -1;
- goto out;
- }
-
-out:
- lbs_deb_leave(LBS_DEB_CMD);
- return ret;
-}
-
-int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
-{
- struct cmd_ds_host_sleep cmd_config;
- int ret;
-
- cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
- cmd_config.criteria = cpu_to_le32(criteria);
- cmd_config.gpio = priv->wol_gpio;
- cmd_config.gap = priv->wol_gap;
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
- if (!ret) {
- lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
- priv->wol_criteria = criteria;
- } else {
- lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
- }
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
-
-static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
- u16 cmd_action)
-{
- struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
- S_DS_GEN);
- psm->action = cpu_to_le16(cmd_action);
- psm->multipledtim = 0;
- switch (cmd_action) {
- case CMD_SUBCMD_ENTER_PS:
- lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
-
- psm->locallisteninterval = 0;
- psm->nullpktinterval = 0;
- psm->multipledtim =
- cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
- break;
-
- case CMD_SUBCMD_EXIT_PS:
- lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
- break;
-
- case CMD_SUBCMD_SLEEP_CONFIRMED:
- lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
- break;
-
- default:
- break;
- }
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
- uint16_t cmd_action, uint16_t *timeout)
-{
- struct cmd_ds_802_11_inactivity_timeout cmd;
- int ret;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
- cmd.action = cpu_to_le16(cmd_action);
-
- if (cmd_action == CMD_ACT_SET)
- cmd.timeout = cpu_to_le16(*timeout);
- else
- cmd.timeout = 0;
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd);
-
- if (!ret)
- *timeout = le16_to_cpu(cmd.timeout);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return 0;
-}
-
-int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
- struct sleep_params *sp)
-{
- struct cmd_ds_802_11_sleep_params cmd;
- int ret;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (cmd_action == CMD_ACT_GET) {
- memset(&cmd, 0, sizeof(cmd));
- } else {
- cmd.error = cpu_to_le16(sp->sp_error);
- cmd.offset = cpu_to_le16(sp->sp_offset);
- cmd.stabletime = cpu_to_le16(sp->sp_stabletime);
- cmd.calcontrol = sp->sp_calcontrol;
- cmd.externalsleepclk = sp->sp_extsleepclk;
- cmd.reserved = cpu_to_le16(sp->sp_reserved);
- }
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(cmd_action);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd);
-
- if (!ret) {
- lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, "
- "calcontrol 0x%x extsleepclk 0x%x\n",
- le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset),
- le16_to_cpu(cmd.stabletime), cmd.calcontrol,
- cmd.externalsleepclk);
-
- sp->sp_error = le16_to_cpu(cmd.error);
- sp->sp_offset = le16_to_cpu(cmd.offset);
- sp->sp_stabletime = le16_to_cpu(cmd.stabletime);
- sp->sp_calcontrol = cmd.calcontrol;
- sp->sp_extsleepclk = cmd.externalsleepclk;
- sp->sp_reserved = le16_to_cpu(cmd.reserved);
- }
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return 0;
-}
-
-int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
- struct assoc_request *assoc)
-{
- struct cmd_ds_802_11_set_wep cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
- cmd.action = cpu_to_le16(cmd_action);
-
- if (cmd_action == CMD_ACT_ADD) {
- int i;
-
- /* default tx key index */
- cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
- CMD_WEP_KEY_INDEX_MASK);
-
- /* Copy key types and material to host command structure */
- for (i = 0; i < 4; i++) {
- struct enc_key *pkey = &assoc->wep_keys[i];
-
- switch (pkey->len) {
- case KEY_LEN_WEP_40:
- cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
- memmove(cmd.keymaterial[i], pkey->key, pkey->len);
- lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
- break;
- case KEY_LEN_WEP_104:
- cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
- memmove(cmd.keymaterial[i], pkey->key, pkey->len);
- lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
- break;
- case 0:
- break;
- default:
- lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
- i, pkey->len);
- ret = -1;
- goto done;
- break;
- }
- }
- } else if (cmd_action == CMD_ACT_REMOVE) {
- /* ACT_REMOVE clears _all_ WEP keys */
-
- /* default tx key index */
- cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
- CMD_WEP_KEY_INDEX_MASK);
- lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
- }
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
-done:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
- uint16_t *enable)
-{
- struct cmd_ds_802_11_enable_rsn cmd;
- int ret;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(cmd_action);
-
- if (cmd_action == CMD_ACT_GET)
- cmd.enable = 0;
- else {
- if (*enable)
- cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
- else
- cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
- lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
- }
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
- if (!ret && cmd_action == CMD_ACT_GET)
- *enable = le16_to_cpu(cmd.enable);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
- struct enc_key *key)
-{
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (key->flags & KEY_INFO_WPA_ENABLED)
- keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
- if (key->flags & KEY_INFO_WPA_UNICAST)
- keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
- if (key->flags & KEY_INFO_WPA_MCAST)
- keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
-
- keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
- keyparam->keytypeid = cpu_to_le16(key->type);
- keyparam->keylen = cpu_to_le16(key->len);
- memcpy(keyparam->key, key->key, key->len);
-
- /* Length field doesn't include the {type,length} header */
- keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
- lbs_deb_leave(LBS_DEB_CMD);
-}
-
-int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
- struct assoc_request *assoc)
-{
- struct cmd_ds_802_11_key_material cmd;
- int ret = 0;
- int index = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd.action = cpu_to_le16(cmd_action);
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
- if (cmd_action == CMD_ACT_GET) {
- cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
- } else {
- memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
-
- if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
- set_one_wpa_key(&cmd.keyParamSet[index],
- &assoc->wpa_unicast_key);
- index++;
- }
-
- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
- set_one_wpa_key(&cmd.keyParamSet[index],
- &assoc->wpa_mcast_key);
- index++;
- }
-
- /* The common header and as many keys as we included */
- cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
- keyParamSet[index]));
- }
- ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
- /* Copy the returned key to driver private data */
- if (!ret && cmd_action == CMD_ACT_GET) {
- void *buf_ptr = cmd.keyParamSet;
- void *resp_end = &(&cmd)[1];
-
- while (buf_ptr < resp_end) {
- struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
- struct enc_key *key;
- uint16_t param_set_len = le16_to_cpu(keyparam->length);
- uint16_t key_len = le16_to_cpu(keyparam->keylen);
- uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
- uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
- void *end;
-
- end = (void *)keyparam + sizeof(keyparam->type)
- + sizeof(keyparam->length) + param_set_len;
-
- /* Make sure we don't access past the end of the IEs */
- if (end > resp_end)
- break;
-
- if (key_flags & KEY_INFO_WPA_UNICAST)
- key = &priv->wpa_unicast_key;
- else if (key_flags & KEY_INFO_WPA_MCAST)
- key = &priv->wpa_mcast_key;
- else
- break;
-
- /* Copy returned key into driver */
- memset(key, 0, sizeof(struct enc_key));
- if (key_len > sizeof(key->key))
- break;
- key->type = key_type;
- key->flags = key_flags;
- key->len = key_len;
- memcpy(key->key, keyparam->key, key->len);
-
- buf_ptr = end + 1;
- }
- }
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action)
-{
- struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd->command = cpu_to_le16(CMD_802_11_RESET);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
- reset->action = cpu_to_le16(cmd_action);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- int cmd_action,
- int cmd_oid, void *pdata_buf)
-{
- struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
- u8 ucTemp;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
-
- cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB);
- cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
-
- switch (cmd_oid) {
- case OID_802_11_INFRASTRUCTURE_MODE:
- {
- u8 mode = (u8) (size_t) pdata_buf;
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u8));
- if (mode == IW_MODE_ADHOC) {
- ucTemp = SNMP_MIB_VALUE_ADHOC;
- } else {
- /* Infra and Auto modes */
- ucTemp = SNMP_MIB_VALUE_INFRA;
- }
-
- memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
-
- break;
- }
-
- case OID_802_11D_ENABLE:
- {
- u32 ulTemp;
-
- pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
-
- if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- ulTemp = *(u32 *)pdata_buf;
- *((__le16 *)(pSNMPMIB->value)) =
- cpu_to_le16((u16) ulTemp);
- }
- break;
- }
-
- case OID_802_11_FRAGMENTATION_THRESHOLD:
- {
- u32 ulTemp;
-
- pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
-
- if (cmd_action == CMD_ACT_GET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
- } else if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- ulTemp = *((u32 *) pdata_buf);
- *((__le16 *)(pSNMPMIB->value)) =
- cpu_to_le16((u16) ulTemp);
-
- }
-
- break;
- }
-
- case OID_802_11_RTS_THRESHOLD:
- {
-
- u32 ulTemp;
- pSNMPMIB->oid = cpu_to_le16(RTSTHRESH_I);
-
- if (cmd_action == CMD_ACT_GET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
- } else if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- ulTemp = *((u32 *)pdata_buf);
- *(__le16 *)(pSNMPMIB->value) =
- cpu_to_le16((u16) ulTemp);
-
- }
- break;
- }
- case OID_802_11_TX_RETRYCOUNT:
- pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
-
- if (cmd_action == CMD_ACT_GET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
- } else if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
- pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- *((__le16 *)(pSNMPMIB->value)) =
- cpu_to_le16((u16) priv->txretrycount);
- }
-
- break;
- default:
- break;
- }
-
- lbs_deb_cmd(
- "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
- le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
- le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
-
- lbs_deb_cmd(
- "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
- le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
- le16_to_cpu(pSNMPMIB->bufsize),
- le16_to_cpu(*(__le16 *) pSNMPMIB->value));
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
-{
-
- struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd->size =
- cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER);
- prtp->action = cpu_to_le16(cmd_action);
-
- lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
- le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
- le16_to_cpu(prtp->action));
-
- switch (cmd_action) {
- case CMD_ACT_TX_POWER_OPT_GET:
- prtp->action = cpu_to_le16(CMD_ACT_GET);
- prtp->currentlevel = 0;
- break;
-
- case CMD_ACT_TX_POWER_OPT_SET_HIGH:
- prtp->action = cpu_to_le16(CMD_ACT_SET);
- prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
- break;
-
- case CMD_ACT_TX_POWER_OPT_SET_MID:
- prtp->action = cpu_to_le16(CMD_ACT_SET);
- prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID);
- break;
-
- case CMD_ACT_TX_POWER_OPT_SET_LOW:
- prtp->action = cpu_to_le16(CMD_ACT_SET);
- prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
- break;
- }
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
-{
- struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
-
- cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
- S_DS_GEN);
-
- monitor->action = cpu_to_le16(cmd_action);
- if (cmd_action == CMD_ACT_SET) {
- monitor->mode =
- cpu_to_le16((u16) (*(u32 *) pdata_buf));
- }
-
- return 0;
-}
-
-static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action)
-{
- struct cmd_ds_802_11_rate_adapt_rateset
- *rateadapt = &cmd->params.rateset;
-
- lbs_deb_enter(LBS_DEB_CMD);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset)
- + S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
-
- rateadapt->action = cpu_to_le16(cmd_action);
- rateadapt->enablehwauto = cpu_to_le16(priv->enablehwauto);
- rateadapt->bitmap = cpu_to_le16(priv->ratebitmap);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-/**
- * @brief Get the current data rate
- *
- * @param priv A pointer to struct lbs_private structure
- *
- * @return The data rate on success, error on failure
- */
-int lbs_get_data_rate(struct lbs_private *priv)
-{
- struct cmd_ds_802_11_data_rate cmd;
- int ret = -1;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_GET_TX_RATE);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
- if (ret)
- goto out;
-
- lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
-
- ret = (int) lbs_fw_index_to_data_rate(cmd.rates[0]);
- lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", ret);
-
-out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Set the data rate
- *
- * @param priv A pointer to struct lbs_private structure
- * @param rate The desired data rate, or 0 to clear a locked rate
- *
- * @return 0 on success, error on failure
- */
-int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
-{
- struct cmd_ds_802_11_data_rate cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
- if (rate > 0) {
- cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
- cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
- if (cmd.rates[0] == 0) {
- lbs_deb_cmd("DATA_RATE: invalid requested rate of"
- " 0x%02X\n", rate);
- ret = 0;
- goto out;
- }
- lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
- } else {
- cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
- lbs_deb_cmd("DATA_RATE: setting auto\n");
- }
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
- if (ret)
- goto out;
-
- lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
-
- /* FIXME: get actual rates FW can do if this command actually returns
- * all data rates supported.
- */
- priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
- lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
-
-out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action)
-{
- struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
-
- lbs_deb_enter(LBS_DEB_CMD);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
- S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR);
-
- lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
- pMCastAdr->action = cpu_to_le16(cmd_action);
- pMCastAdr->nr_of_adrs =
- cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
- memcpy(pMCastAdr->maclist, priv->multicastlist,
- priv->nr_of_multicastmacaddr * ETH_ALEN);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-/**
- * @brief Get the radio channel
- *
- * @param priv A pointer to struct lbs_private structure
- *
- * @return The channel on success, error on failure
- */
-int lbs_get_channel(struct lbs_private *priv)
-{
- struct cmd_ds_802_11_rf_channel cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
- if (ret)
- goto out;
-
- ret = le16_to_cpu(cmd.channel);
- lbs_deb_cmd("current radio channel is %d\n", ret);
-
-out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-int lbs_update_channel(struct lbs_private *priv)
-{
- int ret;
-
- /* the channel in f/w could be out of sync; get the current channel */
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- ret = lbs_get_channel(priv);
- if (ret > 0) {
- priv->curbssparams.channel = ret;
- ret = 0;
- }
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Set the radio channel
- *
- * @param priv A pointer to struct lbs_private structure
- * @param channel The desired channel, or 0 to clear a locked channel
- *
- * @return 0 on success, error on failure
- */
-int lbs_set_channel(struct lbs_private *priv, u8 channel)
-{
- struct cmd_ds_802_11_rf_channel cmd;
- u8 old_channel = priv->curbssparams.channel;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
- cmd.channel = cpu_to_le16(channel);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
- if (ret)
- goto out;
-
- priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel);
- lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
- priv->curbssparams.channel);
-
-out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
- struct cmd_ds_command *cmd)
-{
-
- lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_RSSI);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
- cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
-
- /* reset Beacon SNR/NF/RSSI values */
- priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
- priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
- priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
- priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
- priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
- priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
- u8 cmd_action, void *pdata_buf)
-{
- struct lbs_offset_value *offval;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- offval = (struct lbs_offset_value *)pdata_buf;
-
- switch (le16_to_cpu(cmdptr->command)) {
- case CMD_MAC_REG_ACCESS:
- {
- struct cmd_ds_mac_reg_access *macreg;
-
- cmdptr->size =
- cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
- + S_DS_GEN);
- macreg =
- (struct cmd_ds_mac_reg_access *)&cmdptr->params.
- macreg;
-
- macreg->action = cpu_to_le16(cmd_action);
- macreg->offset = cpu_to_le16((u16) offval->offset);
- macreg->value = cpu_to_le32(offval->value);
-
- break;
- }
-
- case CMD_BBP_REG_ACCESS:
- {
- struct cmd_ds_bbp_reg_access *bbpreg;
-
- cmdptr->size =
- cpu_to_le16(sizeof
- (struct cmd_ds_bbp_reg_access)
- + S_DS_GEN);
- bbpreg =
- (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
- bbpreg;
-
- bbpreg->action = cpu_to_le16(cmd_action);
- bbpreg->offset = cpu_to_le16((u16) offval->offset);
- bbpreg->value = (u8) offval->value;
-
- break;
- }
-
- case CMD_RF_REG_ACCESS:
- {
- struct cmd_ds_rf_reg_access *rfreg;
-
- cmdptr->size =
- cpu_to_le16(sizeof
- (struct cmd_ds_rf_reg_access) +
- S_DS_GEN);
- rfreg =
- (struct cmd_ds_rf_reg_access *)&cmdptr->params.
- rfreg;
-
- rfreg->action = cpu_to_le16(cmd_action);
- rfreg->offset = cpu_to_le16((u16) offval->offset);
- rfreg->value = (u8) offval->value;
-
- break;
- }
-
- default:
- break;
- }
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
-{
- struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
- cmd->command = cpu_to_le16(CMD_BT_ACCESS);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
- cmd->result = 0;
- bt_access->action = cpu_to_le16(cmd_action);
-
- switch (cmd_action) {
- case CMD_ACT_BT_ACCESS_ADD:
- memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
- lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
- break;
- case CMD_ACT_BT_ACCESS_DEL:
- memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
- lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
- break;
- case CMD_ACT_BT_ACCESS_LIST:
- bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
- break;
- case CMD_ACT_BT_ACCESS_RESET:
- break;
- case CMD_ACT_BT_ACCESS_SET_INVERT:
- bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
- break;
- case CMD_ACT_BT_ACCESS_GET_INVERT:
- break;
- default:
- break;
- }
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
-{
- struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
- cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
- cmd->result = 0;
-
- if (pdata_buf)
- memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
- else
- memset(fwt_access, 0, sizeof(*fwt_access));
-
- fwt_access->action = cpu_to_le16(cmd_action);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
- struct cmd_ds_mesh_access *cmd)
-{
- int ret;
-
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
- cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
- cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
- cmd->hdr.result = 0;
-
- cmd->action = cpu_to_le16(cmd_action);
-
- ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return ret;
-}
-
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan)
-{
- struct cmd_ds_mesh_config cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.action = cpu_to_le16(enable);
- cmd.channel = cpu_to_le16(chan);
- cmd.type = cpu_to_le16(priv->mesh_tlv);
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
- if (enable) {
- cmd.length = cpu_to_le16(priv->mesh_ssid_len);
- memcpy(cmd.data, priv->mesh_ssid, priv->mesh_ssid_len);
- }
- lbs_deb_cmd("mesh config enable %d TLV %x channel %d SSID %s\n",
- enable, priv->mesh_tlv, chan,
- escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
- return lbs_cmd_with_response(priv, CMD_MESH_CONFIG, &cmd);
-}
-
-static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action)
-{
- struct cmd_ds_802_11_beacon_control
- *bcn_ctrl = &cmd->params.bcn_ctrl;
-
- lbs_deb_enter(LBS_DEB_CMD);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
- + S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
-
- bcn_ctrl->action = cpu_to_le16(cmd_action);
- bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
- bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static void lbs_queue_cmd(struct lbs_private *priv,
- struct cmd_ctrl_node *cmdnode)
-{
- unsigned long flags;
- int addtail = 1;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- if (!cmdnode) {
- lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
- goto done;
- }
- if (!cmdnode->cmdbuf->size) {
- lbs_deb_host("DNLD_CMD: cmd size is zero\n");
- goto done;
- }
- cmdnode->result = 0;
-
- /* Exit_PS command needs to be queued in the header always. */
- if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
- struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
-
- if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
- if (priv->psstate != PS_STATE_FULL_POWER)
- addtail = 0;
- }
- }
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (addtail)
- list_add_tail(&cmdnode->list, &priv->cmdpendingq);
- else
- list_add(&cmdnode->list, &priv->cmdpendingq);
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
- le16_to_cpu(cmdnode->cmdbuf->command));
-
-done:
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-static void lbs_submit_command(struct lbs_private *priv,
- struct cmd_ctrl_node *cmdnode)
-{
- unsigned long flags;
- struct cmd_header *cmd;
- uint16_t cmdsize;
- uint16_t command;
- int timeo = 5 * HZ;
- int ret;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- cmd = cmdnode->cmdbuf;
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- priv->cur_cmd = cmdnode;
- priv->cur_cmd_retcode = 0;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- cmdsize = le16_to_cpu(cmd->size);
- command = le16_to_cpu(cmd->command);
-
- /* These commands take longer */
- if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE ||
- command == CMD_802_11_AUTHENTICATE)
- timeo = 10 * HZ;
-
- lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
- command, le16_to_cpu(cmd->seqnum), cmdsize);
- lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
-
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
-
- if (ret) {
- lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
- /* Let the timer kick in and retry, and potentially reset
- the whole thing if the condition persists */
- timeo = HZ;
- }
-
- /* Setup the timer after transmit command */
- mod_timer(&priv->command_timer, jiffies + timeo);
-
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-/**
- * This function inserts command node to cmdfreeq
- * after cleans it. Requires priv->driver_lock held.
- */
-static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
- struct cmd_ctrl_node *cmdnode)
-{
- lbs_deb_enter(LBS_DEB_HOST);
-
- if (!cmdnode)
- goto out;
-
- cmdnode->callback = NULL;
- cmdnode->callback_arg = 0;
-
- memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
-
- list_add_tail(&cmdnode->list, &priv->cmdfreeq);
- out:
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
- struct cmd_ctrl_node *ptempcmd)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- __lbs_cleanup_and_insert_cmd(priv, ptempcmd);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-}
-
-void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
- int result)
-{
- if (cmd == priv->cur_cmd)
- priv->cur_cmd_retcode = result;
-
- cmd->result = result;
- cmd->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmd->cmdwait_q);
-
- if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
- __lbs_cleanup_and_insert_cmd(priv, cmd);
- priv->cur_cmd = NULL;
-}
-
-int lbs_set_radio_control(struct lbs_private *priv)
-{
- int ret = 0;
- struct cmd_ds_802_11_radio_control cmd;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_SET);
-
- switch (priv->preamble) {
- case CMD_TYPE_SHORT_PREAMBLE:
- cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
- break;
-
- case CMD_TYPE_LONG_PREAMBLE:
- cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
- break;
-
- case CMD_TYPE_AUTO_PREAMBLE:
- default:
- cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
- break;
- }
-
- if (priv->radioon)
- cmd.control |= cpu_to_le16(TURN_ON_RF);
- else
- cmd.control &= cpu_to_le16(~TURN_ON_RF);
-
- lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
- priv->preamble);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-void lbs_set_mac_control(struct lbs_private *priv)
-{
- struct cmd_ds_mac_control cmd;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(priv->mac_control);
- cmd.reserved = 0;
-
- lbs_cmd_async(priv, CMD_MAC_CONTROL,
- &cmd.hdr, sizeof(cmd));
-
- lbs_deb_leave(LBS_DEB_CMD);
-}
-
-/**
- * @brief This function prepare the command before send to firmware.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param cmd_no command number
- * @param cmd_action command action: GET or SET
- * @param wait_option wait option: wait response or not
- * @param cmd_oid cmd oid: treated as sub command
- * @param pdata_buf A pointer to informaion buffer
- * @return 0 or -1
- */
-int lbs_prepare_and_send_command(struct lbs_private *priv,
- u16 cmd_no,
- u16 cmd_action,
- u16 wait_option, u32 cmd_oid, void *pdata_buf)
-{
- int ret = 0;
- struct cmd_ctrl_node *cmdnode;
- struct cmd_ds_command *cmdptr;
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- if (!priv) {
- lbs_deb_host("PREP_CMD: priv is NULL\n");
- ret = -1;
- goto done;
- }
-
- if (priv->surpriseremoved) {
- lbs_deb_host("PREP_CMD: card removed\n");
- ret = -1;
- goto done;
- }
-
- cmdnode = lbs_get_cmd_ctrl_node(priv);
-
- if (cmdnode == NULL) {
- lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
-
- /* Wake up main thread to execute next command */
- wake_up_interruptible(&priv->waitq);
- ret = -1;
- goto done;
- }
-
- cmdnode->callback = NULL;
- cmdnode->callback_arg = (unsigned long)pdata_buf;
-
- cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
-
- lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
-
- /* Set sequence number, command and INT option */
- priv->seqnum++;
- cmdptr->seqnum = cpu_to_le16(priv->seqnum);
-
- cmdptr->command = cpu_to_le16(cmd_no);
- cmdptr->result = 0;
-
- switch (cmd_no) {
- case CMD_802_11_PS_MODE:
- ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
- break;
-
- case CMD_802_11_ASSOCIATE:
- case CMD_802_11_REASSOCIATE:
- ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
- break;
-
- case CMD_802_11_DEAUTHENTICATE:
- ret = lbs_cmd_80211_deauthenticate(priv, cmdptr);
- break;
-
- case CMD_802_11_AD_HOC_START:
- ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
- break;
-
- case CMD_802_11_RESET:
- ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
- break;
-
- case CMD_802_11_AUTHENTICATE:
- ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
- break;
-
- case CMD_802_11_SNMP_MIB:
- ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
- cmd_action, cmd_oid, pdata_buf);
- break;
-
- case CMD_MAC_REG_ACCESS:
- case CMD_BBP_REG_ACCESS:
- case CMD_RF_REG_ACCESS:
- ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_802_11_RF_TX_POWER:
- ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
- cmd_action, pdata_buf);
- break;
-
- case CMD_802_11_RATE_ADAPT_RATESET:
- ret = lbs_cmd_802_11_rate_adapt_rateset(priv,
- cmdptr, cmd_action);
- break;
-
- case CMD_MAC_MULTICAST_ADR:
- ret = lbs_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
- break;
-
- case CMD_802_11_MONITOR_MODE:
- ret = lbs_cmd_802_11_monitor_mode(cmdptr,
- cmd_action, pdata_buf);
- break;
-
- case CMD_802_11_AD_HOC_JOIN:
- ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
- break;
-
- case CMD_802_11_RSSI:
- ret = lbs_cmd_802_11_rssi(priv, cmdptr);
- break;
-
- case CMD_802_11_AD_HOC_STOP:
- ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
- break;
-
- case CMD_802_11_SET_AFC:
- case CMD_802_11_GET_AFC:
-
- cmdptr->command = cpu_to_le16(cmd_no);
- cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
- S_DS_GEN);
-
- memmove(&cmdptr->params.afc,
- pdata_buf, sizeof(struct cmd_ds_802_11_afc));
-
- ret = 0;
- goto done;
-
- case CMD_802_11D_DOMAIN_INFO:
- ret = lbs_cmd_802_11d_domain_info(priv, cmdptr,
- cmd_no, cmd_action);
- break;
-
- case CMD_802_11_TPC_CFG:
- cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
- cmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
- S_DS_GEN);
-
- memmove(&cmdptr->params.tpccfg,
- pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
-
- ret = 0;
- break;
- case CMD_802_11_LED_GPIO_CTRL:
- {
- struct mrvlietypes_ledgpio *gpio =
- (struct mrvlietypes_ledgpio*)
- cmdptr->params.ledgpio.data;
-
- memmove(&cmdptr->params.ledgpio,
- pdata_buf,
- sizeof(struct cmd_ds_802_11_led_ctrl));
-
- cmdptr->command =
- cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
-
-#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
- cmdptr->size =
- cpu_to_le16(le16_to_cpu(gpio->header.len)
- + S_DS_GEN
- + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
- gpio->header.len = gpio->header.len;
-
- ret = 0;
- break;
- }
-
- case CMD_BT_ACCESS:
- ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_FWT_ACCESS:
- ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_GET_TSF:
- cmdptr->command = cpu_to_le16(CMD_GET_TSF);
- cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
- S_DS_GEN);
- ret = 0;
- break;
- case CMD_802_11_BEACON_CTRL:
- ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
- break;
- default:
- lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no);
- ret = -1;
- break;
- }
-
- /* return error, since the command preparation failed */
- if (ret != 0) {
- lbs_deb_host("PREP_CMD: command preparation failed\n");
- lbs_cleanup_and_insert_cmd(priv, cmdnode);
- ret = -1;
- goto done;
- }
-
- cmdnode->cmdwaitqwoken = 0;
-
- lbs_queue_cmd(priv, cmdnode);
- wake_up_interruptible(&priv->waitq);
-
- if (wait_option & CMD_OPTION_WAITFORRSP) {
- lbs_deb_host("PREP_CMD: wait for response\n");
- might_sleep();
- wait_event_interruptible(cmdnode->cmdwait_q,
- cmdnode->cmdwaitqwoken);
- }
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- if (priv->cur_cmd_retcode) {
- lbs_deb_host("PREP_CMD: command failed with return code %d\n",
- priv->cur_cmd_retcode);
- priv->cur_cmd_retcode = 0;
- ret = -1;
- }
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function allocates the command buffer and link
- * it to command free queue.
- *
- * @param priv A pointer to struct lbs_private structure
- * @return 0 or -1
- */
-int lbs_allocate_cmd_buffer(struct lbs_private *priv)
-{
- int ret = 0;
- u32 bufsize;
- u32 i;
- struct cmd_ctrl_node *cmdarray;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- /* Allocate and initialize the command array */
- bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
- if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
- lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
- ret = -1;
- goto done;
- }
- priv->cmd_array = cmdarray;
-
- /* Allocate and initialize each command buffer in the command array */
- for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
- cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
- if (!cmdarray[i].cmdbuf) {
- lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
- ret = -1;
- goto done;
- }
- }
-
- for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
- init_waitqueue_head(&cmdarray[i].cmdwait_q);
- lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
- }
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function frees the command buffer.
- *
- * @param priv A pointer to struct lbs_private structure
- * @return 0 or -1
- */
-int lbs_free_cmd_buffer(struct lbs_private *priv)
-{
- struct cmd_ctrl_node *cmdarray;
- unsigned int i;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- /* need to check if cmd array is allocated or not */
- if (priv->cmd_array == NULL) {
- lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
- goto done;
- }
-
- cmdarray = priv->cmd_array;
-
- /* Release shared memory buffers */
- for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
- if (cmdarray[i].cmdbuf) {
- kfree(cmdarray[i].cmdbuf);
- cmdarray[i].cmdbuf = NULL;
- }
- }
-
- /* Release cmd_ctrl_node */
- if (priv->cmd_array) {
- kfree(priv->cmd_array);
- priv->cmd_array = NULL;
- }
-
-done:
- lbs_deb_leave(LBS_DEB_HOST);
- return 0;
-}
-
-/**
- * @brief This function gets a free command node if available in
- * command free queue.
- *
- * @param priv A pointer to struct lbs_private structure
- * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
- */
-static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
-{
- struct cmd_ctrl_node *tempnode;
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- if (!priv)
- return NULL;
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (!list_empty(&priv->cmdfreeq)) {
- tempnode = list_first_entry(&priv->cmdfreeq,
- struct cmd_ctrl_node, list);
- list_del(&tempnode->list);
- } else {
- lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
- tempnode = NULL;
- }
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- lbs_deb_leave(LBS_DEB_HOST);
- return tempnode;
-}
-
-/**
- * @brief This function executes next command in command
- * pending queue. It will put fimware back to PS mode
- * if applicable.
- *
- * @param priv A pointer to struct lbs_private structure
- * @return 0 or -1
- */
-int lbs_execute_next_command(struct lbs_private *priv)
-{
- struct cmd_ctrl_node *cmdnode = NULL;
- struct cmd_header *cmd;
- unsigned long flags;
- int ret = 0;
-
- /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
- * only caller to us is lbs_thread() and we get even when a
- * data packet is received */
- lbs_deb_enter(LBS_DEB_THREAD);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (priv->cur_cmd) {
- lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- ret = -1;
- goto done;
- }
-
- if (!list_empty(&priv->cmdpendingq)) {
- cmdnode = list_first_entry(&priv->cmdpendingq,
- struct cmd_ctrl_node, list);
- }
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- if (cmdnode) {
- cmd = cmdnode->cmdbuf;
-
- if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) {
- if ((priv->psstate == PS_STATE_SLEEP) ||
- (priv->psstate == PS_STATE_PRE_SLEEP)) {
- lbs_deb_host(
- "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
- le16_to_cpu(cmd->command),
- priv->psstate);
- ret = -1;
- goto done;
- }
- lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
- "0x%04x in psstate %d\n",
- le16_to_cpu(cmd->command), priv->psstate);
- } else if (priv->psstate != PS_STATE_FULL_POWER) {
- /*
- * 1. Non-PS command:
- * Queue it. set needtowakeup to TRUE if current state
- * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
- * 2. PS command but not Exit_PS:
- * Ignore it.
- * 3. PS command Exit_PS:
- * Set needtowakeup to TRUE if current state is SLEEP,
- * otherwise send this command down to firmware
- * immediately.
- */
- if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) {
- /* Prepare to send Exit PS,
- * this non PS command will be sent later */
- if ((priv->psstate == PS_STATE_SLEEP)
- || (priv->psstate == PS_STATE_PRE_SLEEP)
- ) {
- /* w/ new scheme, it will not reach here.
- since it is blocked in main_thread. */
- priv->needtowakeup = 1;
- } else
- lbs_ps_wakeup(priv, 0);
-
- ret = 0;
- goto done;
- } else {
- /*
- * PS command. Ignore it if it is not Exit_PS.
- * otherwise send it down immediately.
- */
- struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1];
-
- lbs_deb_host(
- "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
- psm->action);
- if (psm->action !=
- cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
- lbs_deb_host(
- "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
- list_del(&cmdnode->list);
- spin_lock_irqsave(&priv->driver_lock, flags);
- lbs_complete_command(priv, cmdnode, 0);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- ret = 0;
- goto done;
- }
-
- if ((priv->psstate == PS_STATE_SLEEP) ||
- (priv->psstate == PS_STATE_PRE_SLEEP)) {
- lbs_deb_host(
- "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
- list_del(&cmdnode->list);
- spin_lock_irqsave(&priv->driver_lock, flags);
- lbs_complete_command(priv, cmdnode, 0);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- priv->needtowakeup = 1;
-
- ret = 0;
- goto done;
- }
-
- lbs_deb_host(
- "EXEC_NEXT_CMD: sending EXIT_PS\n");
- }
- }
- list_del(&cmdnode->list);
- lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
- le16_to_cpu(cmd->command));
- lbs_submit_command(priv, cmdnode);
- } else {
- /*
- * check if in power save mode, if yes, put the device back
- * to PS mode
- */
- if ((priv->psmode != LBS802_11POWERMODECAM) &&
- (priv->psstate == PS_STATE_FULL_POWER) &&
- ((priv->connect_status == LBS_CONNECTED) ||
- (priv->mesh_connect_status == LBS_CONNECTED))) {
- if (priv->secinfo.WPAenabled ||
- priv->secinfo.WPA2enabled) {
- /* check for valid WPA group keys */
- if (priv->wpa_mcast_key.len ||
- priv->wpa_unicast_key.len) {
- lbs_deb_host(
- "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
- " go back to PS_SLEEP");
- lbs_ps_sleep(priv, 0);
- }
- } else {
- lbs_deb_host(
- "EXEC_NEXT_CMD: cmdpendingq empty, "
- "go back to PS_SLEEP");
- lbs_ps_sleep(priv, 0);
- }
- }
- }
-
- ret = 0;
-done:
- lbs_deb_leave(LBS_DEB_THREAD);
- return ret;
-}
-
-void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
-{
- union iwreq_data iwrq;
- u8 buf[50];
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- memset(&iwrq, 0, sizeof(union iwreq_data));
- memset(buf, 0, sizeof(buf));
-
- snprintf(buf, sizeof(buf) - 1, "%s", str);
-
- iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
-
- /* Send Event to upper layer */
- lbs_deb_wext("event indication string %s\n", (char *)buf);
- lbs_deb_wext("event indication length %d\n", iwrq.data.length);
- lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
-
- wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
-
- lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-static void lbs_send_confirmsleep(struct lbs_private *priv)
-{
- unsigned long flags;
- int ret;
-
- lbs_deb_enter(LBS_DEB_HOST);
- lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
- sizeof(confirm_sleep));
-
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
- sizeof(confirm_sleep));
- if (ret) {
- lbs_pr_alert("confirm_sleep failed\n");
- goto out;
- }
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- /* We don't get a response on the sleep-confirmation */
- priv->dnld_sent = DNLD_RES_RECEIVED;
-
- /* If nothing to do, go back to sleep (?) */
- if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
- priv->psstate = PS_STATE_SLEEP;
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-out:
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
-{
- lbs_deb_enter(LBS_DEB_HOST);
-
- /*
- * PS is currently supported only in Infrastructure mode
- * Remove this check if it is to be supported in IBSS mode also
- */
-
- lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
- CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
-
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-/**
- * @brief This function sends Exit_PS command to firmware.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param wait_option wait response or not
- * @return n/a
- */
-void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
-{
- __le32 Localpsmode;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
-
- lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
- CMD_SUBCMD_EXIT_PS,
- wait_option, 0, &Localpsmode);
-
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-/**
- * @brief This function checks condition and prepares to
- * send sleep confirm command to firmware if ok.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param psmode Power Saving mode
- * @return n/a
- */
-void lbs_ps_confirm_sleep(struct lbs_private *priv)
-{
- unsigned long flags =0;
- int allowed = 1;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- if (priv->dnld_sent) {
- allowed = 0;
- lbs_deb_host("dnld_sent was set\n");
- }
-
- /* In-progress command? */
- if (priv->cur_cmd) {
- allowed = 0;
- lbs_deb_host("cur_cmd was set\n");
- }
-
- /* Pending events or command responses? */
- if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
- allowed = 0;
- lbs_deb_host("pending events or command responses\n");
- }
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- if (allowed) {
- lbs_deb_host("sending lbs_ps_confirm_sleep\n");
- lbs_send_confirmsleep(priv);
- } else {
- lbs_deb_host("sleep confirm has been delayed\n");
- }
-
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-
-static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
- uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
- unsigned long callback_arg)
-{
- struct cmd_ctrl_node *cmdnode;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- if (priv->surpriseremoved) {
- lbs_deb_host("PREP_CMD: card removed\n");
- cmdnode = ERR_PTR(-ENOENT);
- goto done;
- }
-
- cmdnode = lbs_get_cmd_ctrl_node(priv);
- if (cmdnode == NULL) {
- lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
-
- /* Wake up main thread to execute next command */
- wake_up_interruptible(&priv->waitq);
- cmdnode = ERR_PTR(-ENOBUFS);
- goto done;
- }
-
- cmdnode->callback = callback;
- cmdnode->callback_arg = callback_arg;
-
- /* Copy the incoming command to the buffer */
- memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
-
- /* Set sequence number, clean result, move to buffer */
- priv->seqnum++;
- cmdnode->cmdbuf->command = cpu_to_le16(command);
- cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size);
- cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum);
- cmdnode->cmdbuf->result = 0;
-
- lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
-
- cmdnode->cmdwaitqwoken = 0;
- lbs_queue_cmd(priv, cmdnode);
- wake_up_interruptible(&priv->waitq);
-
- done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
- return cmdnode;
-}
-
-void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
- struct cmd_header *in_cmd, int in_cmd_size)
-{
- lbs_deb_enter(LBS_DEB_CMD);
- __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
- lbs_cmd_async_callback, 0);
- lbs_deb_leave(LBS_DEB_CMD);
-}
-
-int __lbs_cmd(struct lbs_private *priv, uint16_t command,
- struct cmd_header *in_cmd, int in_cmd_size,
- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
- unsigned long callback_arg)
-{
- struct cmd_ctrl_node *cmdnode;
- unsigned long flags;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
- callback, callback_arg);
- if (IS_ERR(cmdnode)) {
- ret = PTR_ERR(cmdnode);
- goto done;
- }
-
- might_sleep();
- wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- ret = cmdnode->result;
- if (ret)
- lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n",
- command, ret);
-
- __lbs_cleanup_and_insert_cmd(priv, cmdnode);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
-}
-EXPORT_SYMBOL_GPL(__lbs_cmd);
-
-
+++ /dev/null
-/* Copyright (C) 2007, Red Hat, Inc. */
-
-#ifndef _LBS_CMD_H_
-#define _LBS_CMD_H_
-
-#include "hostcmd.h"
-#include "dev.h"
-
-/* lbs_cmd() infers the size of the buffer to copy data back into, from
- the size of the target of the pointer. Since the command to be sent
- may often be smaller, that size is set in cmd->size by the caller.*/
-#define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \
- uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \
- (cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \
- __lbs_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
-})
-
-#define lbs_cmd_with_response(priv, cmdnr, cmd) \
- lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
-
-void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
- struct cmd_header *in_cmd, int in_cmd_size);
-
-int __lbs_cmd(struct lbs_private *priv, uint16_t command,
- struct cmd_header *in_cmd, int in_cmd_size,
- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
- unsigned long callback_arg);
-
-int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
- struct cmd_header *resp);
-
-int lbs_update_hw_spec(struct lbs_private *priv);
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
- struct cmd_ds_mesh_access *cmd);
-
-int lbs_get_data_rate(struct lbs_private *priv);
-int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
-
-int lbs_get_channel(struct lbs_private *priv);
-int lbs_set_channel(struct lbs_private *priv, u8 channel);
-
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
-
-int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria);
-int lbs_suspend(struct lbs_private *priv);
-int lbs_resume(struct lbs_private *priv);
-
-int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
- uint16_t cmd_action, uint16_t *timeout);
-int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
- struct sleep_params *sp);
-int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
- struct assoc_request *assoc);
-int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
- uint16_t *enable);
-int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
- struct assoc_request *assoc);
-
-#endif /* _LBS_CMD_H */
+++ /dev/null
-/**
- * This file contains the handling of command
- * responses as well as events generated by firmware.
- */
-#include <linux/delay.h>
-#include <linux/if_arp.h>
-#include <linux/netdevice.h>
-
-#include <net/iw_handler.h>
-
-#include "host.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "assoc.h"
-#include "wext.h"
-
-/**
- * @brief This function handles disconnect event. it
- * reports disconnect to upper layer, clean tx/rx packets,
- * reset link state etc.
- *
- * @param priv A pointer to struct lbs_private structure
- * @return n/a
- */
-void lbs_mac_event_disconnected(struct lbs_private *priv)
-{
- union iwreq_data wrqu;
-
- if (priv->connect_status != LBS_CONNECTED)
- return;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-
- /*
- * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
- * It causes problem in the Supplicant
- */
-
- msleep_interruptible(1000);
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
- /* report disconnect to upper layer */
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
-
- /* Free Tx and Rx packets */
- kfree_skb(priv->currenttxskb);
- priv->currenttxskb = NULL;
- priv->tx_pending_len = 0;
-
- /* reset SNR/NF/RSSI values */
- memset(priv->SNR, 0x00, sizeof(priv->SNR));
- memset(priv->NF, 0x00, sizeof(priv->NF));
- memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
- memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
- memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
- priv->nextSNRNF = 0;
- priv->numSNRNF = 0;
- priv->connect_status = LBS_DISCONNECTED;
-
- /* Clear out associated SSID and BSSID since connection is
- * no longer valid.
- */
- memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
- memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
- priv->curbssparams.ssid_len = 0;
-
- if (priv->psstate != PS_STATE_FULL_POWER) {
- /* make firmware to exit PS mode */
- lbs_deb_cmd("disconnected, so exit PS mode\n");
- lbs_ps_wakeup(priv, 0);
- }
- lbs_deb_leave(LBS_DEB_ASSOC);
-}
-
-/**
- * @brief This function handles MIC failure event.
- *
- * @param priv A pointer to struct lbs_private structure
- * @para event the event id
- * @return n/a
- */
-static void handle_mic_failureevent(struct lbs_private *priv, u32 event)
-{
- char buf[50];
-
- lbs_deb_enter(LBS_DEB_CMD);
- memset(buf, 0, sizeof(buf));
-
- sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
-
- if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
- strcat(buf, "unicast ");
- } else {
- strcat(buf, "multicast ");
- }
-
- lbs_send_iwevcustom_event(priv, buf);
- lbs_deb_leave(LBS_DEB_CMD);
-}
-
-static int lbs_ret_reg_access(struct lbs_private *priv,
- u16 type, struct cmd_ds_command *resp)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- switch (type) {
- case CMD_RET(CMD_MAC_REG_ACCESS):
- {
- struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
-
- priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- priv->offsetvalue.value = le32_to_cpu(reg->value);
- break;
- }
-
- case CMD_RET(CMD_BBP_REG_ACCESS):
- {
- struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
-
- priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- priv->offsetvalue.value = reg->value;
- break;
- }
-
- case CMD_RET(CMD_RF_REG_ACCESS):
- {
- struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
-
- priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- priv->offsetvalue.value = reg->value;
- break;
- }
-
- default:
- ret = -1;
- }
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
- u16 oid = le16_to_cpu(smib->oid);
- u16 querytype = le16_to_cpu(smib->querytype);
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
- querytype);
- lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
-
- if (querytype == CMD_ACT_GET) {
- switch (oid) {
- case FRAGTHRESH_I:
- priv->fragthsd =
- le16_to_cpu(*((__le16 *)(smib->value)));
- lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
- priv->fragthsd);
- break;
- case RTSTHRESH_I:
- priv->rtsthsd =
- le16_to_cpu(*((__le16 *)(smib->value)));
- lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
- priv->rtsthsd);
- break;
- case SHORT_RETRYLIM_I:
- priv->txretrycount =
- le16_to_cpu(*((__le16 *)(smib->value)));
- lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
- priv->rtsthsd);
- break;
- default:
- break;
- }
- }
-
- lbs_deb_enter(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
-
- lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (rates->action == CMD_ACT_GET) {
- priv->enablehwauto = le16_to_cpu(rates->enablehwauto);
- priv->ratebitmap = le16_to_cpu(rates->bitmap);
- }
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_ret_802_11_rssi(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- /* store the non average value */
- priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
- priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
-
- priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
- priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
-
- priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
- CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
- priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-
- priv->RSSI[TYPE_BEACON][TYPE_AVG] =
- CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
-
- lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
- priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
- priv->RSSI[TYPE_BEACON][TYPE_AVG]);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_beacon_control *bcn_ctrl =
- &resp->params.bcn_ctrl;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (bcn_ctrl->action == CMD_ACT_GET) {
- priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
- priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
- }
-
- lbs_deb_enter(LBS_DEB_CMD);
- return 0;
-}
-
-static inline int handle_cmd_response(struct lbs_private *priv,
- struct cmd_header *cmd_response)
-{
- struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
- int ret = 0;
- unsigned long flags;
- uint16_t respcmd = le16_to_cpu(resp->command);
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- switch (respcmd) {
- case CMD_RET(CMD_MAC_REG_ACCESS):
- case CMD_RET(CMD_BBP_REG_ACCESS):
- case CMD_RET(CMD_RF_REG_ACCESS):
- ret = lbs_ret_reg_access(priv, respcmd, resp);
- break;
-
- case CMD_RET_802_11_ASSOCIATE:
- case CMD_RET(CMD_802_11_ASSOCIATE):
- case CMD_RET(CMD_802_11_REASSOCIATE):
- ret = lbs_ret_80211_associate(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_DISASSOCIATE):
- case CMD_RET(CMD_802_11_DEAUTHENTICATE):
- ret = lbs_ret_80211_disassociate(priv);
- break;
-
- case CMD_RET(CMD_802_11_AD_HOC_START):
- case CMD_RET(CMD_802_11_AD_HOC_JOIN):
- ret = lbs_ret_80211_ad_hoc_start(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_SNMP_MIB):
- ret = lbs_ret_802_11_snmp_mib(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_RF_TX_POWER):
- ret = lbs_ret_802_11_rf_tx_power(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_SET_AFC):
- case CMD_RET(CMD_802_11_GET_AFC):
- spin_lock_irqsave(&priv->driver_lock, flags);
- memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc,
- sizeof(struct cmd_ds_802_11_afc));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- break;
-
- case CMD_RET(CMD_MAC_MULTICAST_ADR):
- case CMD_RET(CMD_802_11_RESET):
- case CMD_RET(CMD_802_11_AUTHENTICATE):
- case CMD_RET(CMD_802_11_BEACON_STOP):
- break;
-
- case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
- ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_RSSI):
- ret = lbs_ret_802_11_rssi(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_AD_HOC_STOP):
- ret = lbs_ret_80211_ad_hoc_stop(priv);
- break;
-
- case CMD_RET(CMD_802_11D_DOMAIN_INFO):
- ret = lbs_ret_802_11d_domain_info(resp);
- break;
-
- case CMD_RET(CMD_802_11_TPC_CFG):
- spin_lock_irqsave(&priv->driver_lock, flags);
- memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
- sizeof(struct cmd_ds_802_11_tpc_cfg));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
- case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
- spin_lock_irqsave(&priv->driver_lock, flags);
- memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio,
- sizeof(struct cmd_ds_802_11_led_ctrl));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
-
- case CMD_RET(CMD_GET_TSF):
- spin_lock_irqsave(&priv->driver_lock, flags);
- memcpy((void *)priv->cur_cmd->callback_arg,
- &resp->params.gettsf.tsfvalue, sizeof(u64));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
- case CMD_RET(CMD_BT_ACCESS):
- spin_lock_irqsave(&priv->driver_lock, flags);
- if (priv->cur_cmd->callback_arg)
- memcpy((void *)priv->cur_cmd->callback_arg,
- &resp->params.bt.addr1, 2 * ETH_ALEN);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
- case CMD_RET(CMD_FWT_ACCESS):
- spin_lock_irqsave(&priv->driver_lock, flags);
- if (priv->cur_cmd->callback_arg)
- memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt,
- sizeof(resp->params.fwt));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
- case CMD_RET(CMD_802_11_BEACON_CTRL):
- ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
- break;
-
- default:
- lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
- le16_to_cpu(resp->command));
- break;
- }
- lbs_deb_leave(LBS_DEB_HOST);
- return ret;
-}
-
-int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
-{
- uint16_t respcmd, curcmd;
- struct cmd_header *resp;
- int ret = 0;
- unsigned long flags;
- uint16_t result;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- mutex_lock(&priv->lock);
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (!priv->cur_cmd) {
- lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
- ret = -1;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- goto done;
- }
-
- resp = (void *)data;
- curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
- respcmd = le16_to_cpu(resp->command);
- result = le16_to_cpu(resp->result);
-
- lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
- respcmd, le16_to_cpu(resp->seqnum), len);
- lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
-
- if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
- lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
- le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- ret = -1;
- goto done;
- }
- if (respcmd != CMD_RET(curcmd) &&
- respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) {
- lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- ret = -1;
- goto done;
- }
-
- if (resp->result == cpu_to_le16(0x0004)) {
- /* 0x0004 means -EAGAIN. Drop the response, let it time out
- and be resubmitted */
- lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n",
- le16_to_cpu(resp->command));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- ret = -1;
- goto done;
- }
-
- /* Now we got response from FW, cancel the command timer */
- del_timer(&priv->command_timer);
- priv->cmd_timed_out = 0;
- if (priv->nr_retries) {
- lbs_pr_info("Received result %x to command %x after %d retries\n",
- result, curcmd, priv->nr_retries);
- priv->nr_retries = 0;
- }
-
- /* Store the response code to cur_cmd_retcode. */
- priv->cur_cmd_retcode = result;
-
- if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
- struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
- u16 action = le16_to_cpu(psmode->action);
-
- lbs_deb_host(
- "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
- result, action);
-
- if (result) {
- lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
- result);
- /*
- * We should not re-try enter-ps command in
- * ad-hoc mode. It takes place in
- * lbs_execute_next_command().
- */
- if (priv->mode == IW_MODE_ADHOC &&
- action == CMD_SUBCMD_ENTER_PS)
- priv->psmode = LBS802_11POWERMODECAM;
- } else if (action == CMD_SUBCMD_ENTER_PS) {
- priv->needtowakeup = 0;
- priv->psstate = PS_STATE_AWAKE;
-
- lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
- if (priv->connect_status != LBS_CONNECTED) {
- /*
- * When Deauth Event received before Enter_PS command
- * response, We need to wake up the firmware.
- */
- lbs_deb_host(
- "disconnected, invoking lbs_ps_wakeup\n");
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- mutex_unlock(&priv->lock);
- lbs_ps_wakeup(priv, 0);
- mutex_lock(&priv->lock);
- spin_lock_irqsave(&priv->driver_lock, flags);
- }
- } else if (action == CMD_SUBCMD_EXIT_PS) {
- priv->needtowakeup = 0;
- priv->psstate = PS_STATE_FULL_POWER;
- lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
- } else {
- lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
- }
-
- lbs_complete_command(priv, priv->cur_cmd, result);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- ret = 0;
- goto done;
- }
-
- /* If the command is not successful, cleanup and return failure */
- if ((result != 0 || !(respcmd & 0x8000))) {
- lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
- result, respcmd);
- /*
- * Handling errors here
- */
- switch (respcmd) {
- case CMD_RET(CMD_GET_HW_SPEC):
- case CMD_RET(CMD_802_11_RESET):
- lbs_deb_host("CMD_RESP: reset failed\n");
- break;
-
- }
- lbs_complete_command(priv, priv->cur_cmd, result);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- ret = -1;
- goto done;
- }
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- if (priv->cur_cmd && priv->cur_cmd->callback) {
- ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
- resp);
- } else
- ret = handle_cmd_response(priv, resp);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (priv->cur_cmd) {
- /* Clean up and Put current command back to cmdfreeq */
- lbs_complete_command(priv, priv->cur_cmd, result);
- }
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-done:
- mutex_unlock(&priv->lock);
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
-}
-
-static int lbs_send_confirmwake(struct lbs_private *priv)
-{
- struct cmd_header cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
- cmd.size = cpu_to_le16(sizeof(cmd));
- cmd.seqnum = cpu_to_le16(++priv->seqnum);
- cmd.result = 0;
-
- lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
- sizeof(cmd));
-
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
- if (ret)
- lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
-
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
-}
-
-int lbs_process_event(struct lbs_private *priv, u32 event)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- switch (event) {
- case MACREG_INT_CODE_LINK_SENSED:
- lbs_deb_cmd("EVENT: link sensed\n");
- break;
-
- case MACREG_INT_CODE_DEAUTHENTICATED:
- lbs_deb_cmd("EVENT: deauthenticated\n");
- lbs_mac_event_disconnected(priv);
- break;
-
- case MACREG_INT_CODE_DISASSOCIATED:
- lbs_deb_cmd("EVENT: disassociated\n");
- lbs_mac_event_disconnected(priv);
- break;
-
- case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
- lbs_deb_cmd("EVENT: link lost\n");
- lbs_mac_event_disconnected(priv);
- break;
-
- case MACREG_INT_CODE_PS_SLEEP:
- lbs_deb_cmd("EVENT: ps sleep\n");
-
- /* handle unexpected PS SLEEP event */
- if (priv->psstate == PS_STATE_FULL_POWER) {
- lbs_deb_cmd(
- "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
- break;
- }
- priv->psstate = PS_STATE_PRE_SLEEP;
-
- lbs_ps_confirm_sleep(priv);
-
- break;
-
- case MACREG_INT_CODE_HOST_AWAKE:
- lbs_deb_cmd("EVENT: host awake\n");
- lbs_send_confirmwake(priv);
- break;
-
- case MACREG_INT_CODE_PS_AWAKE:
- lbs_deb_cmd("EVENT: ps awake\n");
- /* handle unexpected PS AWAKE event */
- if (priv->psstate == PS_STATE_FULL_POWER) {
- lbs_deb_cmd(
- "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
- break;
- }
-
- priv->psstate = PS_STATE_AWAKE;
-
- if (priv->needtowakeup) {
- /*
- * wait for the command processing to finish
- * before resuming sending
- * priv->needtowakeup will be set to FALSE
- * in lbs_ps_wakeup()
- */
- lbs_deb_cmd("waking up ...\n");
- lbs_ps_wakeup(priv, 0);
- }
- break;
-
- case MACREG_INT_CODE_MIC_ERR_UNICAST:
- lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
- handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
- break;
-
- case MACREG_INT_CODE_MIC_ERR_MULTICAST:
- lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
- handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
- break;
-
- case MACREG_INT_CODE_MIB_CHANGED:
- lbs_deb_cmd("EVENT: MIB CHANGED\n");
- break;
- case MACREG_INT_CODE_INIT_DONE:
- lbs_deb_cmd("EVENT: INIT DONE\n");
- break;
- case MACREG_INT_CODE_ADHOC_BCN_LOST:
- lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
- break;
- case MACREG_INT_CODE_RSSI_LOW:
- lbs_pr_alert("EVENT: rssi low\n");
- break;
- case MACREG_INT_CODE_SNR_LOW:
- lbs_pr_alert("EVENT: snr low\n");
- break;
- case MACREG_INT_CODE_MAX_FAIL:
- lbs_pr_alert("EVENT: max fail\n");
- break;
- case MACREG_INT_CODE_RSSI_HIGH:
- lbs_pr_alert("EVENT: rssi high\n");
- break;
- case MACREG_INT_CODE_SNR_HIGH:
- lbs_pr_alert("EVENT: snr high\n");
- break;
-
- case MACREG_INT_CODE_MESH_AUTO_STARTED:
- /* Ignore spurious autostart events if autostart is disabled */
- if (!priv->mesh_autostart_enabled) {
- lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
- break;
- }
- lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
- priv->mesh_connect_status = LBS_CONNECTED;
- if (priv->mesh_open) {
- netif_carrier_on(priv->mesh_dev);
- if (!priv->tx_pending_len)
- netif_wake_queue(priv->mesh_dev);
- }
- priv->mode = IW_MODE_ADHOC;
- schedule_work(&priv->sync_channel);
- break;
-
- default:
- lbs_pr_alert("EVENT: unknown event id %d\n", event);
- break;
- }
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
+++ /dev/null
-#ifndef __COMPAT_H
-#define __COMPAT_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define DECLARE_MAC_BUF(var) char var[18] __maybe_unused
-
-static inline char *print_mac(char *buf, const u8 *addr)
-{
- sprintf(buf, MAC_FMT,
- addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
- return buf;
-}
-
-#endif
+++ /dev/null
-#include <linux/module.h>
-#include <linux/dcache.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <net/iw_handler.h>
-
-#include "dev.h"
-#include "decl.h"
-#include "host.h"
-#include "debugfs.h"
-#include "cmd.h"
-
-static struct dentry *lbs_dir;
-static char *szStates[] = {
- "Connected",
- "Disconnected"
-};
-
-#ifdef PROC_DEBUG
-static void lbs_debug_init(struct lbs_private *priv);
-#endif
-
-static int open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t write_file_dummy(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- return -EINVAL;
-}
-
-static const size_t len = PAGE_SIZE;
-
-static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- size_t pos = 0;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
- ssize_t res;
-
- pos += snprintf(buf+pos, len-pos, "state = %s\n",
- szStates[priv->connect_status]);
- pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
- (u32) priv->regioncode);
-
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-
- free_page(addr);
- return res;
-}
-
-
-static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- size_t pos = 0;
- int numscansdone = 0, res;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
- DECLARE_MAC_BUF(mac);
- struct bss_descriptor * iter_bss;
-
- pos += snprintf(buf+pos, len-pos,
- "# | ch | rssi | bssid | cap | Qual | SSID \n");
-
- mutex_lock(&priv->lock);
- list_for_each_entry (iter_bss, &priv->network_list, list) {
- u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS);
- u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
- u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
-
- pos += snprintf(buf+pos, len-pos,
- "%02u| %03d | %04d | %s |",
- numscansdone, iter_bss->channel, iter_bss->rssi,
- print_mac(mac, iter_bss->bssid));
- pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
- pos += snprintf(buf+pos, len-pos, "%c%c%c |",
- ibss ? 'A' : 'I', privacy ? 'P' : ' ',
- spectrum_mgmt ? 'S' : ' ');
- pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
- pos += snprintf(buf+pos, len-pos, " %s\n",
- escape_essid(iter_bss->ssid, iter_bss->ssid_len));
-
- numscansdone++;
- }
- mutex_unlock(&priv->lock);
-
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-
- free_page(addr);
- return res;
-}
-
-static ssize_t lbs_sleepparams_write(struct file *file,
- const char __user *user_buf, size_t count,
- loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- ssize_t buf_size, ret;
- struct sleep_params sp;
- int p1, p2, p3, p4, p5, p6;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, user_buf, buf_size)) {
- ret = -EFAULT;
- goto out_unlock;
- }
- ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
- if (ret != 6) {
- ret = -EINVAL;
- goto out_unlock;
- }
- sp.sp_error = p1;
- sp.sp_offset = p2;
- sp.sp_stabletime = p3;
- sp.sp_calcontrol = p4;
- sp.sp_extsleepclk = p5;
- sp.sp_reserved = p6;
-
- ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
- if (!ret)
- ret = count;
- else if (ret > 0)
- ret = -EINVAL;
-
-out_unlock:
- free_page(addr);
- return ret;
-}
-
-static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- ssize_t ret;
- size_t pos = 0;
- struct sleep_params sp;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
- if (ret)
- goto out_unlock;
-
- pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
- sp.sp_offset, sp.sp_stabletime,
- sp.sp_calcontrol, sp.sp_extsleepclk,
- sp.sp_reserved);
-
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-
-out_unlock:
- free_page(addr);
- return ret;
-}
-
-/*
- * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
- * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
- * firmware. Here's an example:
- * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
- * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
- * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- *
- * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
- * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
- * defined in mrvlietypes_thresholds
- *
- * This function searches in this TLV data chunk for a given TLV type
- * and returns a pointer to the first data byte of the TLV, or to NULL
- * if the TLV hasn't been found.
- */
-static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
-{
- struct mrvlietypesheader *tlv_h;
- uint16_t length;
- ssize_t pos = 0;
-
- while (pos < size) {
- tlv_h = (struct mrvlietypesheader *) tlv;
- if (!tlv_h->len)
- return NULL;
- if (tlv_h->type == cpu_to_le16(tlv_type))
- return tlv_h;
- length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
- pos += length;
- tlv += length;
- }
- return NULL;
-}
-
-
-static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
- struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct cmd_ds_802_11_subscribe_event *subscribed;
- struct mrvlietypes_thresholds *got;
- struct lbs_private *priv = file->private_data;
- ssize_t ret = 0;
- size_t pos = 0;
- char *buf;
- u8 value;
- u8 freq;
- int events = 0;
-
- buf = (char *)get_zeroed_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
- if (!subscribed) {
- ret = -ENOMEM;
- goto out_page;
- }
-
- subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
- subscribed->action = cpu_to_le16(CMD_ACT_GET);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
- if (ret)
- goto out_cmd;
-
- got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
- if (got) {
- value = got->value;
- freq = got->freq;
- events = le16_to_cpu(subscribed->events);
-
- pos += snprintf(buf, len, "%d %d %d\n", value, freq,
- !!(events & event_mask));
- }
-
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-
- out_cmd:
- kfree(subscribed);
-
- out_page:
- free_page((unsigned long)buf);
- return ret;
-}
-
-
-static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
- struct file *file,
- const char __user *userbuf, size_t count,
- loff_t *ppos)
-{
- struct cmd_ds_802_11_subscribe_event *events;
- struct mrvlietypes_thresholds *tlv;
- struct lbs_private *priv = file->private_data;
- ssize_t buf_size;
- int value, freq, new_mask;
- uint16_t curr_mask;
- char *buf;
- int ret;
-
- buf = (char *)get_zeroed_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- ret = -EFAULT;
- goto out_page;
- }
- ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
- if (ret != 3) {
- ret = -EINVAL;
- goto out_page;
- }
- events = kzalloc(sizeof(*events), GFP_KERNEL);
- if (!events) {
- ret = -ENOMEM;
- goto out_page;
- }
-
- events->hdr.size = cpu_to_le16(sizeof(*events));
- events->action = cpu_to_le16(CMD_ACT_GET);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
- if (ret)
- goto out_events;
-
- curr_mask = le16_to_cpu(events->events);
-
- if (new_mask)
- new_mask = curr_mask | event_mask;
- else
- new_mask = curr_mask & ~event_mask;
-
- /* Now everything is set and we can send stuff down to the firmware */
-
- tlv = (void *)events->tlv;
-
- events->action = cpu_to_le16(CMD_ACT_SET);
- events->events = cpu_to_le16(new_mask);
- tlv->header.type = cpu_to_le16(tlv_type);
- tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
- tlv->value = value;
- if (tlv_type != TLV_TYPE_BCNMISS)
- tlv->freq = freq;
-
- /* The command header, the action, the event mask, and one TLV */
- events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
-
- if (!ret)
- ret = count;
- out_events:
- kfree(events);
- out_page:
- free_page((unsigned long)buf);
- return ret;
-}
-
-
-static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
- file, userbuf, count, ppos);
-}
-
-static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
- file, userbuf, count, ppos);
-}
-
-
-static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
- file, userbuf, count, ppos);
-}
-
-
-
-static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- struct lbs_offset_value offval;
- ssize_t pos = 0;
- int ret;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- offval.offset = priv->mac_offset;
- offval.value = 0;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_MAC_REG_ACCESS, 0,
- CMD_OPTION_WAITFORRSP, 0, &offval);
- mdelay(10);
- pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
- priv->mac_offset, priv->offsetvalue.value);
-
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
- return ret;
-}
-
-static ssize_t lbs_rdmac_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-static ssize_t lbs_wrmac_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
-
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- u32 offset, value;
- struct lbs_offset_value offval;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%x %x", &offset, &value);
- if (res != 2) {
- res = -EFAULT;
- goto out_unlock;
- }
-
- offval.offset = offset;
- offval.value = value;
- res = lbs_prepare_and_send_command(priv,
- CMD_MAC_REG_ACCESS, 1,
- CMD_OPTION_WAITFORRSP, 0, &offval);
- mdelay(10);
-
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- struct lbs_offset_value offval;
- ssize_t pos = 0;
- int ret;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- offval.offset = priv->bbp_offset;
- offval.value = 0;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_BBP_REG_ACCESS, 0,
- CMD_OPTION_WAITFORRSP, 0, &offval);
- mdelay(10);
- pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
- priv->bbp_offset, priv->offsetvalue.value);
-
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
-
- return ret;
-}
-
-static ssize_t lbs_rdbbp_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-static ssize_t lbs_wrbbp_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
-
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- u32 offset, value;
- struct lbs_offset_value offval;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%x %x", &offset, &value);
- if (res != 2) {
- res = -EFAULT;
- goto out_unlock;
- }
-
- offval.offset = offset;
- offval.value = value;
- res = lbs_prepare_and_send_command(priv,
- CMD_BBP_REG_ACCESS, 1,
- CMD_OPTION_WAITFORRSP, 0, &offval);
- mdelay(10);
-
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- struct lbs_offset_value offval;
- ssize_t pos = 0;
- int ret;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- offval.offset = priv->rf_offset;
- offval.value = 0;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_RF_REG_ACCESS, 0,
- CMD_OPTION_WAITFORRSP, 0, &offval);
- mdelay(10);
- pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
- priv->rf_offset, priv->offsetvalue.value);
-
- ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
-
- return ret;
-}
-
-static ssize_t lbs_rdrf_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- priv->rf_offset = simple_strtoul((char *)buf, NULL, 16);
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-static ssize_t lbs_wrrf_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
-
- struct lbs_private *priv = file->private_data;
- ssize_t res, buf_size;
- u32 offset, value;
- struct lbs_offset_value offval;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%x %x", &offset, &value);
- if (res != 2) {
- res = -EFAULT;
- goto out_unlock;
- }
-
- offval.offset = offset;
- offval.value = value;
- res = lbs_prepare_and_send_command(priv,
- CMD_RF_REG_ACCESS, 1,
- CMD_OPTION_WAITFORRSP, 0, &offval);
- mdelay(10);
-
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-#define FOPS(fread, fwrite) { \
- .owner = THIS_MODULE, \
- .open = open_file_generic, \
- .read = (fread), \
- .write = (fwrite), \
-}
-
-struct lbs_debugfs_files {
- char *name;
- int perm;
- struct file_operations fops;
-};
-
-static struct lbs_debugfs_files debugfs_files[] = {
- { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
- { "getscantable", 0444, FOPS(lbs_getscantable,
- write_file_dummy), },
- { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
- lbs_sleepparams_write), },
-};
-
-static struct lbs_debugfs_files debugfs_events_files[] = {
- {"low_rssi", 0644, FOPS(lbs_lowrssi_read,
- lbs_lowrssi_write), },
- {"low_snr", 0644, FOPS(lbs_lowsnr_read,
- lbs_lowsnr_write), },
- {"failure_count", 0644, FOPS(lbs_failcount_read,
- lbs_failcount_write), },
- {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read,
- lbs_bcnmiss_write), },
- {"high_rssi", 0644, FOPS(lbs_highrssi_read,
- lbs_highrssi_write), },
- {"high_snr", 0644, FOPS(lbs_highsnr_read,
- lbs_highsnr_write), },
-};
-
-static struct lbs_debugfs_files debugfs_regs_files[] = {
- {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
- {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
- {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
- {"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), },
- {"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), },
- {"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), },
-};
-
-void lbs_debugfs_init(void)
-{
- if (!lbs_dir)
- lbs_dir = debugfs_create_dir("lbs_wireless", NULL);
-
- return;
-}
-
-void lbs_debugfs_remove(void)
-{
- if (lbs_dir)
- debugfs_remove(lbs_dir);
- return;
-}
-
-void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
-{
- int i;
- struct lbs_debugfs_files *files;
- if (!lbs_dir)
- goto exit;
-
- priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
- if (!priv->debugfs_dir)
- goto exit;
-
- for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
- files = &debugfs_files[i];
- priv->debugfs_files[i] = debugfs_create_file(files->name,
- files->perm,
- priv->debugfs_dir,
- priv,
- &files->fops);
- }
-
- priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
- if (!priv->events_dir)
- goto exit;
-
- for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
- files = &debugfs_events_files[i];
- priv->debugfs_events_files[i] = debugfs_create_file(files->name,
- files->perm,
- priv->events_dir,
- priv,
- &files->fops);
- }
-
- priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
- if (!priv->regs_dir)
- goto exit;
-
- for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
- files = &debugfs_regs_files[i];
- priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
- files->perm,
- priv->regs_dir,
- priv,
- &files->fops);
- }
-
-#ifdef PROC_DEBUG
- lbs_debug_init(priv);
-#endif
-exit:
- return;
-}
-
-void lbs_debugfs_remove_one(struct lbs_private *priv)
-{
- int i;
-
- for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
- debugfs_remove(priv->debugfs_regs_files[i]);
-
- debugfs_remove(priv->regs_dir);
-
- for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
- debugfs_remove(priv->debugfs_events_files[i]);
-
- debugfs_remove(priv->events_dir);
-#ifdef PROC_DEBUG
- debugfs_remove(priv->debugfs_debug);
-#endif
- for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
- debugfs_remove(priv->debugfs_files[i]);
- debugfs_remove(priv->debugfs_dir);
-}
-
-
-
-/* debug entry */
-
-#ifdef PROC_DEBUG
-
-#define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
-#define item_addr(n) (offsetof(struct lbs_private, n))
-
-
-struct debug_data {
- char name[32];
- u32 size;
- size_t addr;
-};
-
-/* To debug any member of struct lbs_private, simply add one line here.
- */
-static struct debug_data items[] = {
- {"psmode", item_size(psmode), item_addr(psmode)},
- {"psstate", item_size(psstate), item_addr(psstate)},
-};
-
-static int num_of_items = ARRAY_SIZE(items);
-
-/**
- * @brief proc read function
- *
- * @param page pointer to buffer
- * @param s read data starting position
- * @param off offset
- * @param cnt counter
- * @param eof end of file flag
- * @param data data to output
- * @return number of output data
- */
-static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- int val = 0;
- size_t pos = 0;
- ssize_t res;
- char *p;
- int i;
- struct debug_data *d;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- p = buf;
-
- d = (struct debug_data *)file->private_data;
-
- for (i = 0; i < num_of_items; i++) {
- if (d[i].size == 1)
- val = *((u8 *) d[i].addr);
- else if (d[i].size == 2)
- val = *((u16 *) d[i].addr);
- else if (d[i].size == 4)
- val = *((u32 *) d[i].addr);
- else if (d[i].size == 8)
- val = *((u64 *) d[i].addr);
-
- pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
- }
-
- res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
-
- free_page(addr);
- return res;
-}
-
-/**
- * @brief proc write function
- *
- * @param f file pointer
- * @param buf pointer to data buffer
- * @param cnt data number to write
- * @param data data to write
- * @return number of data
- */
-static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
- size_t cnt, loff_t *ppos)
-{
- int r, i;
- char *pdata;
- char *p;
- char *p0;
- char *p1;
- char *p2;
- struct debug_data *d = (struct debug_data *)f->private_data;
-
- pdata = kmalloc(cnt, GFP_KERNEL);
- if (pdata == NULL)
- return 0;
-
- if (copy_from_user(pdata, buf, cnt)) {
- lbs_deb_debugfs("Copy from user failed\n");
- kfree(pdata);
- return 0;
- }
-
- p0 = pdata;
- for (i = 0; i < num_of_items; i++) {
- do {
- p = strstr(p0, d[i].name);
- if (p == NULL)
- break;
- p1 = strchr(p, '\n');
- if (p1 == NULL)
- break;
- p0 = p1++;
- p2 = strchr(p, '=');
- if (!p2)
- break;
- p2++;
- r = simple_strtoul(p2, NULL, 0);
- if (d[i].size == 1)
- *((u8 *) d[i].addr) = (u8) r;
- else if (d[i].size == 2)
- *((u16 *) d[i].addr) = (u16) r;
- else if (d[i].size == 4)
- *((u32 *) d[i].addr) = (u32) r;
- else if (d[i].size == 8)
- *((u64 *) d[i].addr) = (u64) r;
- break;
- } while (1);
- }
- kfree(pdata);
-
- return (ssize_t)cnt;
-}
-
-static struct file_operations lbs_debug_fops = {
- .owner = THIS_MODULE,
- .open = open_file_generic,
- .write = lbs_debugfs_write,
- .read = lbs_debugfs_read,
-};
-
-/**
- * @brief create debug proc file
- *
- * @param priv pointer struct lbs_private
- * @param dev pointer net_device
- * @return N/A
- */
-static void lbs_debug_init(struct lbs_private *priv)
-{
- int i;
-
- if (!priv->debugfs_dir)
- return;
-
- for (i = 0; i < num_of_items; i++)
- items[i].addr += (size_t) priv;
-
- priv->debugfs_debug = debugfs_create_file("debug", 0644,
- priv->debugfs_dir, &items[0],
- &lbs_debug_fops);
-}
-#endif
+++ /dev/null
-#ifndef _LBS_DEBUGFS_H_
-#define _LBS_DEBUGFS_H_
-
-void lbs_debugfs_init(void);
-void lbs_debugfs_remove(void);
-
-void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev);
-void lbs_debugfs_remove_one(struct lbs_private *priv);
-
-#endif
+++ /dev/null
-/**
- * This file contains declaration referring to
- * functions defined in other source files
- */
-
-#ifndef _LBS_DECL_H_
-#define _LBS_DECL_H_
-
-#include <linux/device.h>
-
-#include "defs.h"
-
-/** Function Prototype Declaration */
-struct lbs_private;
-struct sk_buff;
-struct net_device;
-struct cmd_ctrl_node;
-struct cmd_ds_command;
-
-void lbs_set_mac_control(struct lbs_private *priv);
-
-void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
-
-int lbs_free_cmd_buffer(struct lbs_private *priv);
-
-int lbs_prepare_and_send_command(struct lbs_private *priv,
- u16 cmd_no,
- u16 cmd_action,
- u16 wait_option, u32 cmd_oid, void *pdata_buf);
-
-int lbs_allocate_cmd_buffer(struct lbs_private *priv);
-int lbs_execute_next_command(struct lbs_private *priv);
-int lbs_process_event(struct lbs_private *priv, u32 event);
-void lbs_queue_event(struct lbs_private *priv, u32 event);
-void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
-
-int lbs_set_radio_control(struct lbs_private *priv);
-u32 lbs_fw_index_to_data_rate(u8 index);
-u8 lbs_data_rate_to_fw_index(u32 rate);
-
-/** The proc fs interface */
-int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
-void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
- int result);
-int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
-int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
-
-int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
-
-void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
-void lbs_ps_confirm_sleep(struct lbs_private *priv);
-void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
-
-struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
- struct lbs_private *priv,
- u8 band,
- u16 channel);
-
-void lbs_mac_event_disconnected(struct lbs_private *priv);
-
-void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
-
-/* main.c */
-struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
- int *cfp_no);
-struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
-int lbs_remove_card(struct lbs_private *priv);
-int lbs_start_card(struct lbs_private *priv);
-int lbs_stop_card(struct lbs_private *priv);
-void lbs_host_to_card_done(struct lbs_private *priv);
-
-int lbs_update_channel(struct lbs_private *priv);
-
-#ifndef CONFIG_IEEE80211
-const char *escape_essid(const char *essid, u8 essid_len);
-#endif
-
-#endif
+++ /dev/null
-/**
- * This header file contains global constant/enum definitions,
- * global variable declaration.
- */
-#ifndef _LBS_DEFS_H_
-#define _LBS_DEFS_H_
-
-#include <linux/spinlock.h>
-
-#ifdef CONFIG_LIBERTAS_DEBUG
-#define DEBUG
-#define PROC_DEBUG
-#endif
-
-#ifndef DRV_NAME
-#define DRV_NAME "libertas"
-#endif
-
-
-#define LBS_DEB_ENTER 0x00000001
-#define LBS_DEB_LEAVE 0x00000002
-#define LBS_DEB_MAIN 0x00000004
-#define LBS_DEB_NET 0x00000008
-#define LBS_DEB_MESH 0x00000010
-#define LBS_DEB_WEXT 0x00000020
-#define LBS_DEB_IOCTL 0x00000040
-#define LBS_DEB_SCAN 0x00000080
-#define LBS_DEB_ASSOC 0x00000100
-#define LBS_DEB_JOIN 0x00000200
-#define LBS_DEB_11D 0x00000400
-#define LBS_DEB_DEBUGFS 0x00000800
-#define LBS_DEB_ETHTOOL 0x00001000
-#define LBS_DEB_HOST 0x00002000
-#define LBS_DEB_CMD 0x00004000
-#define LBS_DEB_RX 0x00008000
-#define LBS_DEB_TX 0x00010000
-#define LBS_DEB_USB 0x00020000
-#define LBS_DEB_CS 0x00040000
-#define LBS_DEB_FW 0x00080000
-#define LBS_DEB_THREAD 0x00100000
-#define LBS_DEB_HEX 0x00200000
-#define LBS_DEB_SDIO 0x00400000
-
-extern unsigned int lbs_debug;
-
-#ifdef DEBUG
-#define LBS_DEB_LL(grp, grpnam, fmt, args...) \
-do { if ((lbs_debug & (grp)) == (grp)) \
- printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
- in_interrupt() ? " (INT)" : "", ## args); } while (0)
-#else
-#define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
-#endif
-
-#define lbs_deb_enter(grp) \
- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
-#define lbs_deb_enter_args(grp, fmt, args...) \
- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
-#define lbs_deb_leave(grp) \
- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
-#define lbs_deb_leave_args(grp, fmt, args...) \
- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
- __func__, ##args);
-#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
-#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
-#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
-#define lbs_deb_wext(fmt, args...) LBS_DEB_LL(LBS_DEB_WEXT, " wext", fmt, ##args)
-#define lbs_deb_ioctl(fmt, args...) LBS_DEB_LL(LBS_DEB_IOCTL, " ioctl", fmt, ##args)
-#define lbs_deb_scan(fmt, args...) LBS_DEB_LL(LBS_DEB_SCAN, " scan", fmt, ##args)
-#define lbs_deb_assoc(fmt, args...) LBS_DEB_LL(LBS_DEB_ASSOC, " assoc", fmt, ##args)
-#define lbs_deb_join(fmt, args...) LBS_DEB_LL(LBS_DEB_JOIN, " join", fmt, ##args)
-#define lbs_deb_11d(fmt, args...) LBS_DEB_LL(LBS_DEB_11D, " 11d", fmt, ##args)
-#define lbs_deb_debugfs(fmt, args...) LBS_DEB_LL(LBS_DEB_DEBUGFS, " debugfs", fmt, ##args)
-#define lbs_deb_ethtool(fmt, args...) LBS_DEB_LL(LBS_DEB_ETHTOOL, " ethtool", fmt, ##args)
-#define lbs_deb_host(fmt, args...) LBS_DEB_LL(LBS_DEB_HOST, " host", fmt, ##args)
-#define lbs_deb_cmd(fmt, args...) LBS_DEB_LL(LBS_DEB_CMD, " cmd", fmt, ##args)
-#define lbs_deb_rx(fmt, args...) LBS_DEB_LL(LBS_DEB_RX, " rx", fmt, ##args)
-#define lbs_deb_tx(fmt, args...) LBS_DEB_LL(LBS_DEB_TX, " tx", fmt, ##args)
-#define lbs_deb_fw(fmt, args...) LBS_DEB_LL(LBS_DEB_FW, " fw", fmt, ##args)
-#define lbs_deb_usb(fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usb", fmt, ##args)
-#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, (dev)->bus_id, ##args)
-#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args)
-#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
-#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " thread", fmt, ##args)
-
-#define lbs_pr_info(format, args...) \
- printk(KERN_INFO DRV_NAME": " format, ## args)
-#define lbs_pr_err(format, args...) \
- printk(KERN_ERR DRV_NAME": " format, ## args)
-#define lbs_pr_alert(format, args...) \
- printk(KERN_ALERT DRV_NAME": " format, ## args)
-
-#ifdef DEBUG
-static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
-{
- int i = 0;
-
- if (len &&
- (lbs_debug & LBS_DEB_HEX) &&
- (lbs_debug & grp))
- {
- for (i = 1; i <= len; i++) {
- if ((i & 0xf) == 1) {
- if (i != 1)
- printk("\n");
- printk(DRV_NAME " %s: ", prompt);
- }
- printk("%02x ", (u8) * buf);
- buf++;
- }
- printk("\n");
- }
-}
-#else
-#define lbs_deb_hex(grp,prompt,buf,len) do {} while (0)
-#endif
-
-
-
-/** Buffer Constants */
-
-/* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
-* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
-* driver has more local TxPDs. Each TxPD on the host memory is associated
-* with a Tx control node. The driver maintains 8 RxPD descriptors for
-* station firmware to store Rx packet information.
-*
-* Current version of MAC has a 32x6 multicast address buffer.
-*
-* 802.11b can have up to 14 channels, the driver keeps the
-* BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
-*/
-
-#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
-#define LBS_NUM_CMD_BUFFERS 10
-#define LBS_CMD_BUFFER_SIZE (2 * 1024)
-#define MRVDRV_MAX_CHANNEL_SIZE 14
-#define MRVDRV_ASSOCIATION_TIME_OUT 255
-#define MRVDRV_SNAP_HEADER_LEN 8
-
-#define LBS_UPLD_SIZE 2312
-#define DEV_NAME_LEN 32
-
-/* Wake criteria for HOST_SLEEP_CFG command */
-#define EHS_WAKE_ON_BROADCAST_DATA 0x0001
-#define EHS_WAKE_ON_UNICAST_DATA 0x0002
-#define EHS_WAKE_ON_MAC_EVENT 0x0004
-#define EHS_WAKE_ON_MULTICAST_DATA 0x0008
-#define EHS_REMOVE_WAKEUP 0xFFFFFFFF
-
-/** Misc constants */
-/* This section defines 802.11 specific contants */
-
-#define MRVDRV_MAX_BSS_DESCRIPTS 16
-#define MRVDRV_MAX_REGION_CODE 6
-
-#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
-#define MRVDRV_MIN_MULTIPLE_DTIM 1
-#define MRVDRV_MAX_MULTIPLE_DTIM 5
-#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1
-
-#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10
-
-#define MRVDRV_CHANNELS_PER_SCAN 4
-#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
-
-#define MRVDRV_MIN_BEACON_INTERVAL 20
-#define MRVDRV_MAX_BEACON_INTERVAL 10000
-#define MRVDRV_BEACON_INTERVAL 100
-
-#define MARVELL_MESH_IE_LENGTH 9
-
-/** INT status Bit Definition*/
-#define MRVDRV_TX_DNLD_RDY 0x0001
-#define MRVDRV_RX_UPLD_RDY 0x0002
-#define MRVDRV_CMD_DNLD_RDY 0x0004
-#define MRVDRV_CMD_UPLD_RDY 0x0008
-#define MRVDRV_CARDEVENT 0x0010
-
-/** TxPD status */
-
-/* Station firmware use TxPD status field to report final Tx transmit
-* result, Bit masks are used to present combined situations.
-*/
-
-#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01
-#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08
-
-/** Tx mesh flag */
-/* Currently we are using normal WDS flag as mesh flag.
- * TODO: change to proper mesh flag when MAC understands it.
- */
-#define TxPD_CONTROL_WDS_FRAME (1<<17)
-#define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME
-
-/** RxPD status */
-
-#define MRVDRV_RXPD_STATUS_OK 0x0001
-
-/** RxPD status - Received packet types */
-/** Rx mesh flag */
-/* Currently we are using normal WDS flag as mesh flag.
- * TODO: change to proper mesh flag when MAC understands it.
- */
-#define RxPD_CONTROL_WDS_FRAME (0x40)
-#define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME
-
-/** RSSI-related defines */
-/* RSSI constants are used to implement 802.11 RSSI threshold
-* indication. if the Rx packet signal got too weak for 5 consecutive
-* times, miniport driver (driver) will report this event to wrapper
-*/
-
-#define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96)
-
-/** RTS/FRAG related defines */
-#define MRVDRV_RTS_MIN_VALUE 0
-#define MRVDRV_RTS_MAX_VALUE 2347
-#define MRVDRV_FRAG_MIN_VALUE 256
-#define MRVDRV_FRAG_MAX_VALUE 2346
-
-/* This is for firmware specific length */
-#define EXTRA_LEN 36
-
-#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
- (ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN)
-
-#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
- (ETH_FRAME_LEN + sizeof(struct rxpd) \
- + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
-
-#define CMD_F_HOSTCMD (1 << 0)
-#define FW_CAPINFO_WPA (1 << 0)
-
-#define KEY_LEN_WPA_AES 16
-#define KEY_LEN_WPA_TKIP 32
-#define KEY_LEN_WEP_104 13
-#define KEY_LEN_WEP_40 5
-
-#define RF_ANTENNA_1 0x1
-#define RF_ANTENNA_2 0x2
-#define RF_ANTENNA_AUTO 0xFFFF
-
-#define BAND_B (0x01)
-#define BAND_G (0x02)
-#define ALL_802_11_BANDS (BAND_B | BAND_G)
-
-/** MACRO DEFINITIONS */
-#define CAL_NF(NF) ((s32)(-(s32)(NF)))
-#define CAL_RSSI(SNR, NF) ((s32)((s32)(SNR) + CAL_NF(NF)))
-#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI)))
-
-#define DEFAULT_BCN_AVG_FACTOR 8
-#define DEFAULT_DATA_AVG_FACTOR 8
-#define AVG_SCALE 100
-#define CAL_AVG_SNR_NF(AVG, SNRNF, N) \
- (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \
- ((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \
- AVG_SCALE)) / N))
-
-#define MAX_RATES 14
-
-#define MAX_LEDS 8
-
-/** Global Variable Declaration */
-extern const char lbs_driver_version[];
-extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE];
-
-extern u8 lbs_bg_rates[MAX_RATES];
-
-/** ENUM definition*/
-/** SNRNF_TYPE */
-enum SNRNF_TYPE {
- TYPE_BEACON = 0,
- TYPE_RXPD,
- MAX_TYPE_B
-};
-
-/** SNRNF_DATA*/
-enum SNRNF_DATA {
- TYPE_NOAVG = 0,
- TYPE_AVG,
- MAX_TYPE_AVG
-};
-
-/** LBS_802_11_POWER_MODE */
-enum LBS_802_11_POWER_MODE {
- LBS802_11POWERMODECAM,
- LBS802_11POWERMODEMAX_PSP,
- LBS802_11POWERMODEFAST_PSP,
- /*not a real mode, defined as an upper bound */
- LBS802_11POWEMODEMAX
-};
-
-/** PS_STATE */
-enum PS_STATE {
- PS_STATE_FULL_POWER,
- PS_STATE_AWAKE,
- PS_STATE_PRE_SLEEP,
- PS_STATE_SLEEP
-};
-
-/** DNLD_STATE */
-enum DNLD_STATE {
- DNLD_RES_RECEIVED,
- DNLD_DATA_SENT,
- DNLD_CMD_SENT
-};
-
-/** LBS_MEDIA_STATE */
-enum LBS_MEDIA_STATE {
- LBS_CONNECTED,
- LBS_DISCONNECTED
-};
-
-/** LBS_802_11_PRIVACY_FILTER */
-enum LBS_802_11_PRIVACY_FILTER {
- LBS802_11PRIVFILTERACCEPTALL,
- LBS802_11PRIVFILTER8021XWEP
-};
-
-/** mv_ms_type */
-enum mv_ms_type {
- MVMS_DAT = 0,
- MVMS_CMD = 1,
- MVMS_TXDONE = 2,
- MVMS_EVENT
-};
-
-/** SNMP_MIB_INDEX_e */
-enum SNMP_MIB_INDEX_e {
- DESIRED_BSSTYPE_I = 0,
- OP_RATESET_I,
- BCNPERIOD_I,
- DTIMPERIOD_I,
- ASSOCRSP_TIMEOUT_I,
- RTSTHRESH_I,
- SHORT_RETRYLIM_I,
- LONG_RETRYLIM_I,
- FRAGTHRESH_I,
- DOT11D_I,
- DOT11H_I,
- MANUFID_I,
- PRODID_I,
- MANUF_OUI_I,
- MANUF_NAME_I,
- MANUF_PRODNAME_I,
- MANUF_PRODVER_I,
-};
-
-/** KEY_TYPE_ID */
-enum KEY_TYPE_ID {
- KEY_TYPE_ID_WEP = 0,
- KEY_TYPE_ID_TKIP,
- KEY_TYPE_ID_AES
-};
-
-/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */
-enum KEY_INFO_WPA {
- KEY_INFO_WPA_MCAST = 0x01,
- KEY_INFO_WPA_UNICAST = 0x02,
- KEY_INFO_WPA_ENABLED = 0x04
-};
-
-/** SNMP_MIB_VALUE_e */
-enum SNMP_MIB_VALUE_e {
- SNMP_MIB_VALUE_INFRA = 1,
- SNMP_MIB_VALUE_ADHOC
-};
-
-/* Default values for fwt commands. */
-#define FWT_DEFAULT_METRIC 0
-#define FWT_DEFAULT_DIR 1
-/* Default Rate, 11Mbps */
-#define FWT_DEFAULT_RATE 3
-#define FWT_DEFAULT_SSN 0xffffffff
-#define FWT_DEFAULT_DSN 0
-#define FWT_DEFAULT_HOPCOUNT 0
-#define FWT_DEFAULT_TTL 0
-#define FWT_DEFAULT_EXPIRATION 0
-#define FWT_DEFAULT_SLEEPMODE 0
-#define FWT_DEFAULT_SNR 0
-
-#endif
+++ /dev/null
-/**
- * This file contains definitions and data structures specific
- * to Marvell 802.11 NIC. It contains the Device Information
- * structure struct lbs_private..
- */
-#ifndef _LBS_DEV_H_
-#define _LBS_DEV_H_
-
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <linux/ethtool.h>
-#include <linux/debugfs.h>
-#include <net/ieee80211.h>
-
-#include "defs.h"
-#include "hostcmd.h"
-
-extern struct ethtool_ops lbs_ethtool_ops;
-
-#define MAX_BSSID_PER_CHANNEL 16
-
-#define NR_TX_QUEUE 3
-
-/* For the extended Scan */
-#define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL * \
- MRVDRV_MAX_CHANNEL_SIZE + 1
-
-#define MAX_REGION_CHANNEL_NUM 2
-
-/** Chan-freq-TxPower mapping table*/
-struct chan_freq_power {
- /** channel Number */
- u16 channel;
- /** frequency of this channel */
- u32 freq;
- /** Max allowed Tx power level */
- u16 maxtxpower;
- /** TRUE:channel unsupported; FLASE:supported*/
- u8 unsupported;
-};
-
-/** region-band mapping table*/
-struct region_channel {
- /** TRUE if this entry is valid */
- u8 valid;
- /** region code for US, Japan ... */
- u8 region;
- /** band B/G/A, used for BAND_CONFIG cmd */
- u8 band;
- /** Actual No. of elements in the array below */
- u8 nrcfp;
- /** chan-freq-txpower mapping table*/
- struct chan_freq_power *CFP;
-};
-
-struct lbs_802_11_security {
- u8 WPAenabled;
- u8 WPA2enabled;
- u8 wep_enabled;
- u8 auth_mode;
-};
-
-/** Current Basic Service Set State Structure */
-struct current_bss_params {
- /** bssid */
- u8 bssid[ETH_ALEN];
- /** ssid */
- u8 ssid[IW_ESSID_MAX_SIZE + 1];
- u8 ssid_len;
-
- /** band */
- u8 band;
- /** channel */
- u8 channel;
- /** zero-terminated array of supported data rates */
- u8 rates[MAX_RATES + 1];
-};
-
-/** sleep_params */
-struct sleep_params {
- uint16_t sp_error;
- uint16_t sp_offset;
- uint16_t sp_stabletime;
- uint8_t sp_calcontrol;
- uint8_t sp_extsleepclk;
- uint16_t sp_reserved;
-};
-
-/* Mesh statistics */
-struct lbs_mesh_stats {
- u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
- u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
- u32 fwd_drop_ttl; /* Fwd: TTL zero */
- u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
- u32 fwd_drop_noroute; /* Fwd: No route to Destination */
- u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
- u32 drop_blind; /* Rx: Dropped by blinding table */
- u32 tx_failed_cnt; /* Tx: Failed transmissions */
-};
-
-/** Private structure for the MV device */
-struct lbs_private {
- int mesh_open;
- int infra_open;
- int mesh_autostart_enabled;
-
- char name[DEV_NAME_LEN];
-
- void *card;
- struct net_device *dev;
-
- struct net_device_stats stats;
- struct net_device *mesh_dev; /* Virtual device */
- struct net_device *rtap_net_dev;
-
- struct iw_statistics wstats;
- struct lbs_mesh_stats mstats;
- struct dentry *debugfs_dir;
- struct dentry *debugfs_debug;
- struct dentry *debugfs_files[6];
-
- struct dentry *events_dir;
- struct dentry *debugfs_events_files[6];
-
- struct dentry *regs_dir;
- struct dentry *debugfs_regs_files[6];
-
- u32 mac_offset;
- u32 bbp_offset;
- u32 rf_offset;
-
- /* Download sent:
- bit0 1/0=data_sent/data_tx_done,
- bit1 1/0=cmd_sent/cmd_tx_done,
- all other bits reserved 0 */
- u8 dnld_sent;
-
- /** thread to service interrupts */
- struct task_struct *main_thread;
- wait_queue_head_t waitq;
- struct workqueue_struct *work_thread;
-
- /** Scanning */
- struct delayed_work scan_work;
- struct delayed_work assoc_work;
- struct work_struct sync_channel;
- /* remember which channel was scanned last, != 0 if currently scanning */
- int scan_channel;
- u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
- u8 scan_ssid_len;
-
- /** Hardware access */
- int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
-
- /* Wake On LAN */
- uint32_t wol_criteria;
- uint8_t wol_gpio;
- uint8_t wol_gap;
-
- /** Wlan adapter data structure*/
- /** STATUS variables */
- u32 fwrelease;
- u32 fwcapinfo;
-
- struct mutex lock;
-
- /* TX packet ready to be sent... */
- int tx_pending_len; /* -1 while building packet */
-
- u8 tx_pending_buf[LBS_UPLD_SIZE];
- /* protected by hard_start_xmit serialization */
-
- /** command-related variables */
- u16 seqnum;
-
- struct cmd_ctrl_node *cmd_array;
- /** Current command */
- struct cmd_ctrl_node *cur_cmd;
- int cur_cmd_retcode;
- /** command Queues */
- /** Free command buffers */
- struct list_head cmdfreeq;
- /** Pending command buffers */
- struct list_head cmdpendingq;
-
- wait_queue_head_t cmd_pending;
-
- /* Command responses sent from the hardware to the driver */
- u8 resp_idx;
- u8 resp_buf[2][LBS_UPLD_SIZE];
- u32 resp_len[2];
-
- /* Events sent from hardware to driver */
- struct kfifo *event_fifo;
-
- /* nickname */
- u8 nodename[16];
-
- /** spin locks */
- spinlock_t driver_lock;
-
- /** Timers */
- struct timer_list command_timer;
- int nr_retries;
- int cmd_timed_out;
-
- /** current ssid/bssid related parameters*/
- struct current_bss_params curbssparams;
-
- uint16_t mesh_tlv;
- u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1];
- u8 mesh_ssid_len;
-
- /* IW_MODE_* */
- u8 mode;
-
- /* Scan results list */
- struct list_head network_list;
- struct list_head network_free_list;
- struct bss_descriptor *networks;
-
- u16 beacon_period;
- u8 beacon_enable;
- u8 adhoccreate;
-
- /** capability Info used in Association, start, join */
- u16 capability;
-
- /** MAC address information */
- u8 current_addr[ETH_ALEN];
- u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
- u32 nr_of_multicastmacaddr;
-
- /** 802.11 statistics */
-// struct cmd_DS_802_11_GET_STAT wlan802_11Stat;
-
- u16 enablehwauto;
- u16 ratebitmap;
-
- u32 fragthsd;
- u32 rtsthsd;
-
- u8 txretrycount;
-
- /** Tx-related variables (for single packet tx) */
- struct sk_buff *currenttxskb;
-
- /** NIC Operation characteristics */
- u16 mac_control;
- u32 connect_status;
- u32 mesh_connect_status;
- u16 regioncode;
- u16 txpowerlevel;
-
- /** POWER MANAGEMENT AND PnP SUPPORT */
- u8 surpriseremoved;
-
- u16 psmode; /* Wlan802_11PowermodeCAM=disable
- Wlan802_11PowermodeMAX_PSP=enable */
- u32 psstate;
- char ps_supported;
- u8 needtowakeup;
-
- struct assoc_request * pending_assoc_req;
- struct assoc_request * in_progress_assoc_req;
-
- /** Encryption parameter */
- struct lbs_802_11_security secinfo;
-
- /** WEP keys */
- struct enc_key wep_keys[4];
- u16 wep_tx_keyidx;
-
- /** WPA keys */
- struct enc_key wpa_mcast_key;
- struct enc_key wpa_unicast_key;
-
- /** WPA Information Elements*/
- u8 wpa_ie[MAX_WPA_IE_LEN];
- u8 wpa_ie_len;
-
- /** Requested Signal Strength*/
- u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
- u16 NF[MAX_TYPE_B][MAX_TYPE_AVG];
- u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG];
- u8 rawSNR[DEFAULT_DATA_AVG_FACTOR];
- u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
- u16 nextSNRNF;
- u16 numSNRNF;
-
- u8 radioon;
- u32 preamble;
-
- /** data rate stuff */
- u8 cur_rate;
- u8 auto_rate;
-
- /** RF calibration data */
-
-#define MAX_REGION_CHANNEL_NUM 2
- /** region channel data */
- struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
-
- struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM];
-
- /** 11D and Domain Regulatory Data */
- struct lbs_802_11d_domain_reg domainreg;
- struct parsed_region_chan_11d parsed_region_chan;
-
- /** FSM variable for 11d support */
- u32 enable11d;
-
- /** MISCELLANEOUS */
- struct lbs_offset_value offsetvalue;
-
- u32 monitormode;
- u8 fw_ready;
-};
-
-extern struct cmd_confirm_sleep confirm_sleep;
-
-/**
- * @brief Structure used to store information for each beacon/probe response
- */
-struct bss_descriptor {
- u8 bssid[ETH_ALEN];
-
- u8 ssid[IW_ESSID_MAX_SIZE + 1];
- u8 ssid_len;
-
- u16 capability;
- u32 rssi;
- u32 channel;
- u16 beaconperiod;
- u32 atimwindow;
-
- /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
- u8 mode;
-
- /* zero-terminated array of supported data rates */
- u8 rates[MAX_RATES + 1];
-
- unsigned long last_scanned;
-
- union ieeetypes_phyparamset phyparamset;
- union IEEEtypes_ssparamset ssparamset;
-
- struct ieeetypes_countryinfofullset countryinfo;
-
- u8 wpa_ie[MAX_WPA_IE_LEN];
- size_t wpa_ie_len;
- u8 rsn_ie[MAX_WPA_IE_LEN];
- size_t rsn_ie_len;
-
- u8 mesh;
-
- struct list_head list;
-};
-
-/** Association request
- *
- * Encapsulates all the options that describe a specific assocation request
- * or configuration of the wireless card's radio, mode, and security settings.
- */
-struct assoc_request {
-#define ASSOC_FLAG_SSID 1
-#define ASSOC_FLAG_CHANNEL 2
-#define ASSOC_FLAG_BAND 3
-#define ASSOC_FLAG_MODE 4
-#define ASSOC_FLAG_BSSID 5
-#define ASSOC_FLAG_WEP_KEYS 6
-#define ASSOC_FLAG_WEP_TX_KEYIDX 7
-#define ASSOC_FLAG_WPA_MCAST_KEY 8
-#define ASSOC_FLAG_WPA_UCAST_KEY 9
-#define ASSOC_FLAG_SECINFO 10
-#define ASSOC_FLAG_WPA_IE 11
- unsigned long flags;
-
- u8 ssid[IW_ESSID_MAX_SIZE + 1];
- u8 ssid_len;
- u8 channel;
- u8 band;
- u8 mode;
- u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
-
- /** WEP keys */
- struct enc_key wep_keys[4];
- u16 wep_tx_keyidx;
-
- /** WPA keys */
- struct enc_key wpa_mcast_key;
- struct enc_key wpa_unicast_key;
-
- struct lbs_802_11_security secinfo;
-
- /** WPA Information Elements*/
- u8 wpa_ie[MAX_WPA_IE_LEN];
- u8 wpa_ie_len;
-
- /* BSS to associate with for infrastructure of Ad-Hoc join */
- struct bss_descriptor bss;
-};
-
-#endif
+++ /dev/null
-#include <linux/netdevice.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-
-#include "host.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "wext.h"
-#include "cmd.h"
-
-static const char * mesh_stat_strings[]= {
- "drop_duplicate_bcast",
- "drop_ttl_zero",
- "drop_no_fwd_route",
- "drop_no_buffers",
- "fwded_unicast_cnt",
- "fwded_bcast_cnt",
- "drop_blind_table",
- "tx_failed_cnt"
-};
-
-static void lbs_ethtool_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
-
- snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
- priv->fwrelease >> 24 & 0xff,
- priv->fwrelease >> 16 & 0xff,
- priv->fwrelease >> 8 & 0xff,
- priv->fwrelease & 0xff);
- strcpy(info->driver, "libertas");
- strcpy(info->version, lbs_driver_version);
-}
-
-/* All 8388 parts have 16KiB EEPROM size at the time of writing.
- * In case that changes this needs fixing.
- */
-#define LBS_EEPROM_LEN 16384
-
-static int lbs_ethtool_get_eeprom_len(struct net_device *dev)
-{
- return LBS_EEPROM_LEN;
-}
-
-static int lbs_ethtool_get_eeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 * bytes)
-{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
- struct cmd_ds_802_11_eeprom_access cmd;
- int ret;
-
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-
- if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
- eeprom->len > LBS_EEPROM_READ_LEN) {
- ret = -EINVAL;
- goto out;
- }
-
- cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
- LBS_EEPROM_READ_LEN + eeprom->len);
- cmd.action = cpu_to_le16(CMD_ACT_GET);
- cmd.offset = cpu_to_le16(eeprom->offset);
- cmd.len = cpu_to_le16(eeprom->len);
- ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
- if (!ret)
- memcpy(bytes, cmd.value, eeprom->len);
-
-out:
- lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
- return ret;
-}
-
-static void lbs_ethtool_get_stats(struct net_device *dev,
- struct ethtool_stats *stats, uint64_t *data)
-{
- struct lbs_private *priv = dev->priv;
- struct cmd_ds_mesh_access mesh_access;
- int ret;
-
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-
- /* Get Mesh Statistics */
- ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
-
- if (ret) {
- memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
- return;
- }
-
- priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
- priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
- priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
- priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
- priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
- priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
- priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
- priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
-
- data[0] = priv->mstats.fwd_drop_rbt;
- data[1] = priv->mstats.fwd_drop_ttl;
- data[2] = priv->mstats.fwd_drop_noroute;
- data[3] = priv->mstats.fwd_drop_nobuf;
- data[4] = priv->mstats.fwd_unicast_cnt;
- data[5] = priv->mstats.fwd_bcast_cnt;
- data[6] = priv->mstats.drop_blind;
- data[7] = priv->mstats.tx_failed_cnt;
-
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-}
-
-static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset)
-{
- struct lbs_private *priv = dev->priv;
-
- if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
- return MESH_STATS_NUM;
-
- return -EOPNOTSUPP;
-}
-
-static void lbs_ethtool_get_strings(struct net_device *dev,
- uint32_t stringset, uint8_t *s)
-{
- int i;
-
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-
- switch (stringset) {
- case ETH_SS_STATS:
- for (i=0; i < MESH_STATS_NUM; i++) {
- memcpy(s + i * ETH_GSTRING_LEN,
- mesh_stat_strings[i],
- ETH_GSTRING_LEN);
- }
- break;
- }
- lbs_deb_enter(LBS_DEB_ETHTOOL);
-}
-
-static void lbs_ethtool_get_wol(struct net_device *dev,
- struct ethtool_wolinfo *wol)
-{
- struct lbs_private *priv = dev->priv;
-
- if (priv->wol_criteria == 0xffffffff) {
- /* Interface driver didn't configure wake */
- wol->supported = wol->wolopts = 0;
- return;
- }
-
- wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
-
- if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
- wol->wolopts |= WAKE_UCAST;
- if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
- wol->wolopts |= WAKE_MCAST;
- if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA)
- wol->wolopts |= WAKE_BCAST;
- if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT)
- wol->wolopts |= WAKE_PHY;
-}
-
-static int lbs_ethtool_set_wol(struct net_device *dev,
- struct ethtool_wolinfo *wol)
-{
- struct lbs_private *priv = dev->priv;
- uint32_t criteria = 0;
-
- if (priv->wol_criteria == 0xffffffff && wol->wolopts)
- return -EOPNOTSUPP;
-
- if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
- return -EOPNOTSUPP;
-
- if (wol->wolopts & WAKE_UCAST) criteria |= EHS_WAKE_ON_UNICAST_DATA;
- if (wol->wolopts & WAKE_MCAST) criteria |= EHS_WAKE_ON_MULTICAST_DATA;
- if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA;
- if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT;
-
- return lbs_host_sleep_cfg(priv, criteria);
-}
-
-struct ethtool_ops lbs_ethtool_ops = {
- .get_drvinfo = lbs_ethtool_get_drvinfo,
- .get_eeprom = lbs_ethtool_get_eeprom,
- .get_eeprom_len = lbs_ethtool_get_eeprom_len,
- .get_sset_count = lbs_ethtool_get_sset_count,
- .get_ethtool_stats = lbs_ethtool_get_stats,
- .get_strings = lbs_ethtool_get_strings,
- .get_wol = lbs_ethtool_get_wol,
- .set_wol = lbs_ethtool_set_wol,
-};
-
+++ /dev/null
-/**
- * This file contains definitions of WLAN commands.
- */
-
-#ifndef _LBS_HOST_H_
-#define _LBS_HOST_H_
-
-/** PUBLIC DEFINITIONS */
-#define DEFAULT_AD_HOC_CHANNEL 6
-#define DEFAULT_AD_HOC_CHANNEL_A 36
-
-/** IEEE 802.11 oids */
-#define OID_802_11_SSID 0x00008002
-#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008
-#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009
-#define OID_802_11_RTS_THRESHOLD 0x0000800A
-#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D
-#define OID_802_11_SUPPORTED_RATES 0x0000800E
-#define OID_802_11_STATISTICS 0x00008012
-#define OID_802_11_TX_RETRYCOUNT 0x0000801D
-#define OID_802_11D_ENABLE 0x00008020
-
-#define CMD_OPTION_WAITFORRSP 0x0002
-
-/** Host command IDs */
-
-/* Return command are almost always the same as the host command, but with
- * bit 15 set high. There are a few exceptions, though...
- */
-#define CMD_RET(cmd) (0x8000 | cmd)
-
-/* Return command convention exceptions: */
-#define CMD_RET_802_11_ASSOCIATE 0x8012
-
-/* Command codes */
-#define CMD_GET_HW_SPEC 0x0003
-#define CMD_EEPROM_UPDATE 0x0004
-#define CMD_802_11_RESET 0x0005
-#define CMD_802_11_SCAN 0x0006
-#define CMD_802_11_GET_LOG 0x000b
-#define CMD_MAC_MULTICAST_ADR 0x0010
-#define CMD_802_11_AUTHENTICATE 0x0011
-#define CMD_802_11_EEPROM_ACCESS 0x0059
-#define CMD_802_11_ASSOCIATE 0x0050
-#define CMD_802_11_SET_WEP 0x0013
-#define CMD_802_11_GET_STAT 0x0014
-#define CMD_802_3_GET_STAT 0x0015
-#define CMD_802_11_SNMP_MIB 0x0016
-#define CMD_MAC_REG_MAP 0x0017
-#define CMD_BBP_REG_MAP 0x0018
-#define CMD_MAC_REG_ACCESS 0x0019
-#define CMD_BBP_REG_ACCESS 0x001a
-#define CMD_RF_REG_ACCESS 0x001b
-#define CMD_802_11_RADIO_CONTROL 0x001c
-#define CMD_802_11_RF_CHANNEL 0x001d
-#define CMD_802_11_RF_TX_POWER 0x001e
-#define CMD_802_11_RSSI 0x001f
-#define CMD_802_11_RF_ANTENNA 0x0020
-#define CMD_802_11_PS_MODE 0x0021
-#define CMD_802_11_DATA_RATE 0x0022
-#define CMD_RF_REG_MAP 0x0023
-#define CMD_802_11_DEAUTHENTICATE 0x0024
-#define CMD_802_11_REASSOCIATE 0x0025
-#define CMD_802_11_DISASSOCIATE 0x0026
-#define CMD_MAC_CONTROL 0x0028
-#define CMD_802_11_AD_HOC_START 0x002b
-#define CMD_802_11_AD_HOC_JOIN 0x002c
-#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
-#define CMD_802_11_ENABLE_RSN 0x002f
-#define CMD_802_11_SET_AFC 0x003c
-#define CMD_802_11_GET_AFC 0x003d
-#define CMD_802_11_AD_HOC_STOP 0x0040
-#define CMD_802_11_HOST_SLEEP_CFG 0x0043
-#define CMD_802_11_WAKEUP_CONFIRM 0x0044
-#define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045
-#define CMD_802_11_BEACON_STOP 0x0049
-#define CMD_802_11_MAC_ADDRESS 0x004d
-#define CMD_802_11_LED_GPIO_CTRL 0x004e
-#define CMD_802_11_EEPROM_ACCESS 0x0059
-#define CMD_802_11_BAND_CONFIG 0x0058
-#define CMD_802_11D_DOMAIN_INFO 0x005b
-#define CMD_802_11_KEY_MATERIAL 0x005e
-#define CMD_802_11_SLEEP_PARAMS 0x0066
-#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
-#define CMD_802_11_SLEEP_PERIOD 0x0068
-#define CMD_802_11_TPC_CFG 0x0072
-#define CMD_802_11_FW_WAKE_METHOD 0x0074
-#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
-#define CMD_802_11_RATE_ADAPT_RATESET 0x0076
-#define CMD_802_11_TX_RATE_QUERY 0x007f
-#define CMD_GET_TSF 0x0080
-#define CMD_BT_ACCESS 0x0087
-#define CMD_FWT_ACCESS 0x0095
-#define CMD_802_11_MONITOR_MODE 0x0098
-#define CMD_MESH_ACCESS 0x009b
-#define CMD_MESH_CONFIG 0x00a3
-#define CMD_SET_BOOT2_VER 0x00a5
-#define CMD_802_11_BEACON_CTRL 0x00b0
-
-/* For the IEEE Power Save */
-#define CMD_SUBCMD_ENTER_PS 0x0030
-#define CMD_SUBCMD_EXIT_PS 0x0031
-#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034
-#define CMD_SUBCMD_FULL_POWERDOWN 0x0035
-#define CMD_SUBCMD_FULL_POWERUP 0x0036
-
-#define CMD_ENABLE_RSN 0x0001
-#define CMD_DISABLE_RSN 0x0000
-
-#define CMD_ACT_GET 0x0000
-#define CMD_ACT_SET 0x0001
-#define CMD_ACT_GET_AES 0x0002
-#define CMD_ACT_SET_AES 0x0003
-#define CMD_ACT_REMOVE_AES 0x0004
-
-/* Define action or option for CMD_802_11_SET_WEP */
-#define CMD_ACT_ADD 0x0002
-#define CMD_ACT_REMOVE 0x0004
-#define CMD_ACT_USE_DEFAULT 0x0008
-
-#define CMD_TYPE_WEP_40_BIT 0x01
-#define CMD_TYPE_WEP_104_BIT 0x02
-
-#define CMD_NUM_OF_WEP_KEYS 4
-
-#define CMD_WEP_KEY_INDEX_MASK 0x3fff
-
-/* Define action or option for CMD_802_11_RESET */
-#define CMD_ACT_HALT 0x0003
-
-/* Define action or option for CMD_802_11_SCAN */
-#define CMD_BSS_TYPE_BSS 0x0001
-#define CMD_BSS_TYPE_IBSS 0x0002
-#define CMD_BSS_TYPE_ANY 0x0003
-
-/* Define action or option for CMD_802_11_SCAN */
-#define CMD_SCAN_TYPE_ACTIVE 0x0000
-#define CMD_SCAN_TYPE_PASSIVE 0x0001
-
-#define CMD_SCAN_RADIO_TYPE_BG 0
-
-#define CMD_SCAN_PROBE_DELAY_TIME 0
-
-/* Define action or option for CMD_MAC_CONTROL */
-#define CMD_ACT_MAC_RX_ON 0x0001
-#define CMD_ACT_MAC_TX_ON 0x0002
-#define CMD_ACT_MAC_LOOPBACK_ON 0x0004
-#define CMD_ACT_MAC_WEP_ENABLE 0x0008
-#define CMD_ACT_MAC_INT_ENABLE 0x0010
-#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020
-#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040
-#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
-#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
-#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
-
-/* Define action or option for CMD_802_11_RADIO_CONTROL */
-#define CMD_TYPE_AUTO_PREAMBLE 0x0001
-#define CMD_TYPE_SHORT_PREAMBLE 0x0002
-#define CMD_TYPE_LONG_PREAMBLE 0x0003
-
-/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
-#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
-#define CMD_SUBSCRIBE_SNR_LOW 0x0002
-#define CMD_SUBSCRIBE_FAILCOUNT 0x0004
-#define CMD_SUBSCRIBE_BCNMISS 0x0008
-#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
-#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
-
-#define TURN_ON_RF 0x01
-#define RADIO_ON 0x01
-#define RADIO_OFF 0x00
-
-#define SET_AUTO_PREAMBLE 0x05
-#define SET_SHORT_PREAMBLE 0x03
-#define SET_LONG_PREAMBLE 0x01
-
-/* Define action or option for CMD_802_11_RF_CHANNEL */
-#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
-#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
-
-/* Define action or option for CMD_802_11_RF_TX_POWER */
-#define CMD_ACT_TX_POWER_OPT_GET 0x0000
-#define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007
-#define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004
-#define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000
-
-#define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007
-#define CMD_ACT_TX_POWER_INDEX_MID 0x0004
-#define CMD_ACT_TX_POWER_INDEX_LOW 0x0000
-
-/* Define action or option for CMD_802_11_DATA_RATE */
-#define CMD_ACT_SET_TX_AUTO 0x0000
-#define CMD_ACT_SET_TX_FIX_RATE 0x0001
-#define CMD_ACT_GET_TX_RATE 0x0002
-
-#define CMD_ACT_SET_RX 0x0001
-#define CMD_ACT_SET_TX 0x0002
-#define CMD_ACT_SET_BOTH 0x0003
-#define CMD_ACT_GET_RX 0x0004
-#define CMD_ACT_GET_TX 0x0008
-#define CMD_ACT_GET_BOTH 0x000c
-
-/* Define action or option for CMD_802_11_PS_MODE */
-#define CMD_TYPE_CAM 0x0000
-#define CMD_TYPE_MAX_PSP 0x0001
-#define CMD_TYPE_FAST_PSP 0x0002
-
-/* Options for CMD_802_11_FW_WAKE_METHOD */
-#define CMD_WAKE_METHOD_UNCHANGED 0x0000
-#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
-#define CMD_WAKE_METHOD_GPIO 0x0002
-
-/* Define action or option for CMD_BT_ACCESS */
-enum cmd_bt_access_opts {
- /* The bt commands start at 5 instead of 1 because the old dft commands
- * are mapped to 1-4. These old commands are no longer maintained and
- * should not be called.
- */
- CMD_ACT_BT_ACCESS_ADD = 5,
- CMD_ACT_BT_ACCESS_DEL,
- CMD_ACT_BT_ACCESS_LIST,
- CMD_ACT_BT_ACCESS_RESET,
- CMD_ACT_BT_ACCESS_SET_INVERT,
- CMD_ACT_BT_ACCESS_GET_INVERT
-};
-
-/* Define action or option for CMD_FWT_ACCESS */
-enum cmd_fwt_access_opts {
- CMD_ACT_FWT_ACCESS_ADD = 1,
- CMD_ACT_FWT_ACCESS_DEL,
- CMD_ACT_FWT_ACCESS_LOOKUP,
- CMD_ACT_FWT_ACCESS_LIST,
- CMD_ACT_FWT_ACCESS_LIST_ROUTE,
- CMD_ACT_FWT_ACCESS_LIST_NEIGHBOR,
- CMD_ACT_FWT_ACCESS_RESET,
- CMD_ACT_FWT_ACCESS_CLEANUP,
- CMD_ACT_FWT_ACCESS_TIME,
-};
-
-/* Define action or option for CMD_MESH_ACCESS */
-enum cmd_mesh_access_opts {
- CMD_ACT_MESH_GET_TTL = 1,
- CMD_ACT_MESH_SET_TTL,
- CMD_ACT_MESH_GET_STATS,
- CMD_ACT_MESH_GET_ANYCAST,
- CMD_ACT_MESH_SET_ANYCAST,
- CMD_ACT_MESH_SET_LINK_COSTS,
- CMD_ACT_MESH_GET_LINK_COSTS,
- CMD_ACT_MESH_SET_BCAST_RATE,
- CMD_ACT_MESH_GET_BCAST_RATE,
- CMD_ACT_MESH_SET_RREQ_DELAY,
- CMD_ACT_MESH_GET_RREQ_DELAY,
- CMD_ACT_MESH_SET_ROUTE_EXP,
- CMD_ACT_MESH_GET_ROUTE_EXP,
- CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
- CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
-};
-
-/** Card Event definition */
-#define MACREG_INT_CODE_TX_PPA_FREE 0
-#define MACREG_INT_CODE_TX_DMA_DONE 1
-#define MACREG_INT_CODE_LINK_LOST_W_SCAN 2
-#define MACREG_INT_CODE_LINK_LOST_NO_SCAN 3
-#define MACREG_INT_CODE_LINK_SENSED 4
-#define MACREG_INT_CODE_CMD_FINISHED 5
-#define MACREG_INT_CODE_MIB_CHANGED 6
-#define MACREG_INT_CODE_INIT_DONE 7
-#define MACREG_INT_CODE_DEAUTHENTICATED 8
-#define MACREG_INT_CODE_DISASSOCIATED 9
-#define MACREG_INT_CODE_PS_AWAKE 10
-#define MACREG_INT_CODE_PS_SLEEP 11
-#define MACREG_INT_CODE_MIC_ERR_MULTICAST 13
-#define MACREG_INT_CODE_MIC_ERR_UNICAST 14
-#define MACREG_INT_CODE_WM_AWAKE 15
-#define MACREG_INT_CODE_DEEP_SLEEP_AWAKE 16
-#define MACREG_INT_CODE_ADHOC_BCN_LOST 17
-#define MACREG_INT_CODE_HOST_AWAKE 18
-#define MACREG_INT_CODE_STOP_TX 19
-#define MACREG_INT_CODE_START_TX 20
-#define MACREG_INT_CODE_CHANNEL_SWITCH 21
-#define MACREG_INT_CODE_MEASUREMENT_RDY 22
-#define MACREG_INT_CODE_WMM_CHANGE 23
-#define MACREG_INT_CODE_BG_SCAN_REPORT 24
-#define MACREG_INT_CODE_RSSI_LOW 25
-#define MACREG_INT_CODE_SNR_LOW 26
-#define MACREG_INT_CODE_MAX_FAIL 27
-#define MACREG_INT_CODE_RSSI_HIGH 28
-#define MACREG_INT_CODE_SNR_HIGH 29
-#define MACREG_INT_CODE_MESH_AUTO_STARTED 35
-#define MACREG_INT_CODE_FIRMWARE_READY 48
-
-#endif
+++ /dev/null
-/*
- * This file contains the function prototypes, data structure
- * and defines for all the host/station commands
- */
-#ifndef _LBS_HOSTCMD_H
-#define _LBS_HOSTCMD_H
-
-#include <linux/wireless.h>
-#include "11d.h"
-#include "types.h"
-
-/* 802.11-related definitions */
-
-/* TxPD descriptor */
-struct txpd {
- /* Current Tx packet status */
- __le32 tx_status;
- /* Tx control */
- __le32 tx_control;
- __le32 tx_packet_location;
- /* Tx packet length */
- __le16 tx_packet_length;
- /* First 2 byte of destination MAC address */
- u8 tx_dest_addr_high[2];
- /* Last 4 byte of destination MAC address */
- u8 tx_dest_addr_low[4];
- /* Pkt Priority */
- u8 priority;
- /* Pkt Trasnit Power control */
- u8 powermgmt;
- /* Amount of time the packet has been queued in the driver (units = 2ms) */
- u8 pktdelay_2ms;
- /* reserved */
- u8 reserved1;
-};
-
-/* RxPD Descriptor */
-struct rxpd {
- /* Current Rx packet status */
- __le16 status;
-
- /* SNR */
- u8 snr;
-
- /* Tx control */
- u8 rx_control;
-
- /* Pkt length */
- __le16 pkt_len;
-
- /* Noise Floor */
- u8 nf;
-
- /* Rx Packet Rate */
- u8 rx_rate;
-
- /* Pkt addr */
- __le32 pkt_ptr;
-
- /* Next Rx RxPD addr */
- __le32 next_rxpd_ptr;
-
- /* Pkt Priority */
- u8 priority;
- u8 reserved[3];
-};
-
-struct cmd_header {
- __le16 command;
- __le16 size;
- __le16 seqnum;
- __le16 result;
-} __attribute__ ((packed));
-
-struct cmd_ctrl_node {
- struct list_head list;
- int result;
- /* command response */
- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *);
- unsigned long callback_arg;
- /* command data */
- struct cmd_header *cmdbuf;
- /* wait queue */
- u16 cmdwaitqwoken;
- wait_queue_head_t cmdwait_q;
-};
-
-/* Generic structure to hold all key types. */
-struct enc_key {
- u16 len;
- u16 flags; /* KEY_INFO_* from defs.h */
- u16 type; /* KEY_TYPE_* from defs.h */
- u8 key[32];
-};
-
-/* lbs_offset_value */
-struct lbs_offset_value {
- u32 offset;
- u32 value;
-};
-
-/* Define general data structure */
-/* cmd_DS_GEN */
-struct cmd_ds_gen {
- __le16 command;
- __le16 size;
- __le16 seqnum;
- __le16 result;
- void *cmdresp[0];
-};
-
-#define S_DS_GEN sizeof(struct cmd_ds_gen)
-
-
-/*
- * Define data structure for CMD_GET_HW_SPEC
- * This structure defines the response for the GET_HW_SPEC command
- */
-struct cmd_ds_get_hw_spec {
- struct cmd_header hdr;
-
- /* HW Interface version number */
- __le16 hwifversion;
- /* HW version number */
- __le16 version;
- /* Max number of TxPD FW can handle */
- __le16 nr_txpd;
- /* Max no of Multicast address */
- __le16 nr_mcast_adr;
- /* MAC address */
- u8 permanentaddr[6];
-
- /* region Code */
- __le16 regioncode;
-
- /* Number of antenna used */
- __le16 nr_antenna;
-
- /* FW release number, example 0x01030304 = 2.3.4p1 */
- __le32 fwrelease;
-
- /* Base Address of TxPD queue */
- __le32 wcb_base;
- /* Read Pointer of RxPd queue */
- __le32 rxpd_rdptr;
-
- /* Write Pointer of RxPd queue */
- __le32 rxpd_wrptr;
-
- /*FW/HW capability */
- __le32 fwcapinfo;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_reset {
- __le16 action;
-};
-
-struct cmd_ds_802_11_subscribe_event {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 events;
-
- /* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
- * number of TLVs. From the v5.1 manual, those TLVs would add up to
- * 40 bytes. However, future firmware might add additional TLVs, so I
- * bump this up a bit.
- */
- uint8_t tlv[128];
-};
-
-/*
- * This scan handle Country Information IE(802.11d compliant)
- * Define data structure for CMD_802_11_SCAN
- */
-struct cmd_ds_802_11_scan {
- struct cmd_header hdr;
-
- uint8_t bsstype;
- uint8_t bssid[ETH_ALEN];
- uint8_t tlvbuffer[0];
-#if 0
- mrvlietypes_ssidparamset_t ssidParamSet;
- mrvlietypes_chanlistparamset_t ChanListParamSet;
- mrvlietypes_ratesparamset_t OpRateSet;
-#endif
-};
-
-struct cmd_ds_802_11_scan_rsp {
- struct cmd_header hdr;
-
- __le16 bssdescriptsize;
- uint8_t nr_sets;
- uint8_t bssdesc_and_tlvbuffer[0];
-};
-
-struct cmd_ds_802_11_get_log {
- struct cmd_header hdr;
-
- __le32 mcasttxframe;
- __le32 failed;
- __le32 retry;
- __le32 multiretry;
- __le32 framedup;
- __le32 rtssuccess;
- __le32 rtsfailure;
- __le32 ackfailure;
- __le32 rxfrag;
- __le32 mcastrxframe;
- __le32 fcserror;
- __le32 txframe;
- __le32 wepundecryptable;
-};
-
-struct cmd_ds_mac_control {
- struct cmd_header hdr;
- __le16 action;
- u16 reserved;
-};
-
-struct cmd_ds_mac_multicast_adr {
- __le16 action;
- __le16 nr_of_adrs;
- u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-};
-
-struct cmd_ds_802_11_authenticate {
- u8 macaddr[ETH_ALEN];
- u8 authtype;
- u8 reserved[10];
-};
-
-struct cmd_ds_802_11_deauthenticate {
- u8 macaddr[6];
- __le16 reasoncode;
-};
-
-struct cmd_ds_802_11_associate {
- u8 peerstaaddr[6];
- __le16 capability;
- __le16 listeninterval;
- __le16 bcnperiod;
- u8 dtimperiod;
-
-#if 0
- mrvlietypes_ssidparamset_t ssidParamSet;
- mrvlietypes_phyparamset_t phyparamset;
- mrvlietypes_ssparamset_t ssparamset;
- mrvlietypes_ratesparamset_t ratesParamSet;
-#endif
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_disassociate {
- u8 destmacaddr[6];
- __le16 reasoncode;
-};
-
-struct cmd_ds_802_11_associate_rsp {
- struct ieeetypes_assocrsp assocRsp;
-};
-
-struct cmd_ds_802_11_ad_hoc_result {
- u8 pad[3];
- u8 bssid[ETH_ALEN];
-};
-
-struct cmd_ds_802_11_set_wep {
- struct cmd_header hdr;
-
- /* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
- __le16 action;
-
- /* key Index selected for Tx */
- __le16 keyindex;
-
- /* 40, 128bit or TXWEP */
- uint8_t keytype[4];
- uint8_t keymaterial[4][16];
-};
-
-struct cmd_ds_802_3_get_stat {
- __le32 xmitok;
- __le32 rcvok;
- __le32 xmiterror;
- __le32 rcverror;
- __le32 rcvnobuffer;
- __le32 rcvcrcerror;
-};
-
-struct cmd_ds_802_11_get_stat {
- __le32 txfragmentcnt;
- __le32 mcasttxframecnt;
- __le32 failedcnt;
- __le32 retrycnt;
- __le32 Multipleretrycnt;
- __le32 rtssuccesscnt;
- __le32 rtsfailurecnt;
- __le32 ackfailurecnt;
- __le32 frameduplicatecnt;
- __le32 rxfragmentcnt;
- __le32 mcastrxframecnt;
- __le32 fcserrorcnt;
- __le32 bcasttxframecnt;
- __le32 bcastrxframecnt;
- __le32 txbeacon;
- __le32 rxbeacon;
- __le32 wepundecryptable;
-};
-
-struct cmd_ds_802_11_snmp_mib {
- __le16 querytype;
- __le16 oid;
- __le16 bufsize;
- u8 value[128];
-};
-
-struct cmd_ds_mac_reg_map {
- __le16 buffersize;
- u8 regmap[128];
- __le16 reserved;
-};
-
-struct cmd_ds_bbp_reg_map {
- __le16 buffersize;
- u8 regmap[128];
- __le16 reserved;
-};
-
-struct cmd_ds_rf_reg_map {
- __le16 buffersize;
- u8 regmap[64];
- __le16 reserved;
-};
-
-struct cmd_ds_mac_reg_access {
- __le16 action;
- __le16 offset;
- __le32 value;
-};
-
-struct cmd_ds_bbp_reg_access {
- __le16 action;
- __le16 offset;
- u8 value;
- u8 reserved[3];
-};
-
-struct cmd_ds_rf_reg_access {
- __le16 action;
- __le16 offset;
- u8 value;
- u8 reserved[3];
-};
-
-struct cmd_ds_802_11_radio_control {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 control;
-};
-
-struct cmd_ds_802_11_beacon_control {
- __le16 action;
- __le16 beacon_enable;
- __le16 beacon_period;
-};
-
-struct cmd_ds_802_11_sleep_params {
- struct cmd_header hdr;
-
- /* ACT_GET/ACT_SET */
- __le16 action;
-
- /* Sleep clock error in ppm */
- __le16 error;
-
- /* Wakeup offset in usec */
- __le16 offset;
-
- /* Clock stabilization time in usec */
- __le16 stabletime;
-
- /* control periodic calibration */
- uint8_t calcontrol;
-
- /* control the use of external sleep clock */
- uint8_t externalsleepclk;
-
- /* reserved field, should be set to zero */
- __le16 reserved;
-};
-
-struct cmd_ds_802_11_inactivity_timeout {
- struct cmd_header hdr;
-
- /* ACT_GET/ACT_SET */
- __le16 action;
-
- /* Inactivity timeout in msec */
- __le16 timeout;
-};
-
-struct cmd_ds_802_11_rf_channel {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 channel;
- __le16 rftype; /* unused */
- __le16 reserved; /* unused */
- u8 channellist[32]; /* unused */
-};
-
-struct cmd_ds_802_11_rssi {
- /* weighting factor */
- __le16 N;
-
- __le16 reserved_0;
- __le16 reserved_1;
- __le16 reserved_2;
-};
-
-struct cmd_ds_802_11_rssi_rsp {
- __le16 SNR;
- __le16 noisefloor;
- __le16 avgSNR;
- __le16 avgnoisefloor;
-};
-
-struct cmd_ds_802_11_mac_address {
- struct cmd_header hdr;
-
- __le16 action;
- u8 macadd[ETH_ALEN];
-};
-
-struct cmd_ds_802_11_rf_tx_power {
- __le16 action;
- __le16 currentlevel;
-};
-
-struct cmd_ds_802_11_rf_antenna {
- __le16 action;
-
- /* Number of antennas or 0xffff(diversity) */
- __le16 antennamode;
-
-};
-
-struct cmd_ds_802_11_monitor_mode {
- __le16 action;
- __le16 mode;
-};
-
-struct cmd_ds_set_boot2_ver {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 version;
-};
-
-struct cmd_ds_802_11_fw_wake_method {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 method;
-};
-
-struct cmd_ds_802_11_sleep_period {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 period;
-};
-
-struct cmd_ds_802_11_ps_mode {
- __le16 action;
- __le16 nullpktinterval;
- __le16 multipledtim;
- __le16 reserved;
- __le16 locallisteninterval;
-};
-
-struct cmd_confirm_sleep {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 nullpktinterval;
- __le16 multipledtim;
- __le16 reserved;
- __le16 locallisteninterval;
-};
-
-struct cmd_ds_802_11_data_rate {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 reserved;
- u8 rates[MAX_RATES];
-};
-
-struct cmd_ds_802_11_rate_adapt_rateset {
- __le16 action;
- __le16 enablehwauto;
- __le16 bitmap;
-};
-
-struct cmd_ds_802_11_ad_hoc_start {
- u8 ssid[IW_ESSID_MAX_SIZE];
- u8 bsstype;
- __le16 beaconperiod;
- u8 dtimperiod;
- union IEEEtypes_ssparamset ssparamset;
- union ieeetypes_phyparamset phyparamset;
- __le16 probedelay;
- __le16 capability;
- u8 rates[MAX_RATES];
- u8 tlv_memory_size_pad[100];
-} __attribute__ ((packed));
-
-struct adhoc_bssdesc {
- u8 bssid[6];
- u8 ssid[32];
- u8 type;
- __le16 beaconperiod;
- u8 dtimperiod;
- __le64 timestamp;
- __le64 localtime;
- union ieeetypes_phyparamset phyparamset;
- union IEEEtypes_ssparamset ssparamset;
- __le16 capability;
- u8 rates[MAX_RATES];
-
- /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
- * Adhoc join command and will cause a binary layout mismatch with
- * the firmware
- */
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_ad_hoc_join {
- struct adhoc_bssdesc bss;
- __le16 failtimeout;
- __le16 probedelay;
-
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_enable_rsn {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 enable;
-} __attribute__ ((packed));
-
-struct MrvlIEtype_keyParamSet {
- /* type ID */
- __le16 type;
-
- /* length of Payload */
- __le16 length;
-
- /* type of key: WEP=0, TKIP=1, AES=2 */
- __le16 keytypeid;
-
- /* key control Info specific to a keytypeid */
- __le16 keyinfo;
-
- /* length of key */
- __le16 keylen;
-
- /* key material of size keylen */
- u8 key[32];
-};
-
-struct cmd_ds_host_sleep {
- struct cmd_header hdr;
- __le32 criteria;
- uint8_t gpio;
- uint8_t gap;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_key_material {
- struct cmd_header hdr;
-
- __le16 action;
- struct MrvlIEtype_keyParamSet keyParamSet[2];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_eeprom_access {
- struct cmd_header hdr;
- __le16 action;
- __le16 offset;
- __le16 len;
- /* firmware says it returns a maximum of 20 bytes */
-#define LBS_EEPROM_READ_LEN 20
- u8 value[LBS_EEPROM_READ_LEN];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_tpc_cfg {
- __le16 action;
- u8 enable;
- s8 P0;
- s8 P1;
- s8 P2;
- u8 usesnr;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_led_ctrl {
- __le16 action;
- __le16 numled;
- u8 data[288];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_afc {
- __le16 afc_auto;
- union {
- struct {
- __le16 threshold;
- __le16 period;
- };
- struct {
- __le16 timing_offset; /* signed */
- __le16 carrier_offset; /* signed */
- };
- };
-} __attribute__ ((packed));
-
-struct cmd_tx_rate_query {
- __le16 txrate;
-} __attribute__ ((packed));
-
-struct cmd_ds_get_tsf {
- __le64 tsfvalue;
-} __attribute__ ((packed));
-
-struct cmd_ds_bt_access {
- __le16 action;
- __le32 id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct cmd_ds_fwt_access {
- __le16 action;
- __le32 id;
- u8 valid;
- u8 da[ETH_ALEN];
- u8 dir;
- u8 ra[ETH_ALEN];
- __le32 ssn;
- __le32 dsn;
- __le32 metric;
- u8 rate;
- u8 hopcount;
- u8 ttl;
- __le32 expiration;
- u8 sleepmode;
- __le32 snr;
- __le32 references;
- u8 prec[ETH_ALEN];
-} __attribute__ ((packed));
-
-
-struct cmd_ds_mesh_config {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 channel;
- __le16 type;
- __le16 length;
- u8 data[128]; /* last position reserved */
-} __attribute__ ((packed));
-
-
-struct cmd_ds_mesh_access {
- struct cmd_header hdr;
-
- __le16 action;
- __le32 data[32]; /* last position reserved */
-} __attribute__ ((packed));
-
-/* Number of stats counters returned by the firmware */
-#define MESH_STATS_NUM 8
-
-struct cmd_ds_command {
- /* command header */
- __le16 command;
- __le16 size;
- __le16 seqnum;
- __le16 result;
-
- /* command Body */
- union {
- struct cmd_ds_802_11_ps_mode psmode;
- struct cmd_ds_802_11_associate associate;
- struct cmd_ds_802_11_deauthenticate deauth;
- struct cmd_ds_802_11_ad_hoc_start ads;
- struct cmd_ds_802_11_reset reset;
- struct cmd_ds_802_11_ad_hoc_result result;
- struct cmd_ds_802_11_authenticate auth;
- struct cmd_ds_802_11_get_stat gstat;
- struct cmd_ds_802_3_get_stat gstat_8023;
- struct cmd_ds_802_11_snmp_mib smib;
- struct cmd_ds_802_11_rf_tx_power txp;
- struct cmd_ds_802_11_rf_antenna rant;
- struct cmd_ds_802_11_monitor_mode monitor;
- struct cmd_ds_802_11_rate_adapt_rateset rateset;
- struct cmd_ds_mac_multicast_adr madr;
- struct cmd_ds_802_11_ad_hoc_join adj;
- struct cmd_ds_802_11_rssi rssi;
- struct cmd_ds_802_11_rssi_rsp rssirsp;
- struct cmd_ds_802_11_disassociate dassociate;
- struct cmd_ds_mac_reg_access macreg;
- struct cmd_ds_bbp_reg_access bbpreg;
- struct cmd_ds_rf_reg_access rfreg;
-
- struct cmd_ds_802_11d_domain_info domaininfo;
- struct cmd_ds_802_11d_domain_info domaininforesp;
-
- struct cmd_ds_802_11_tpc_cfg tpccfg;
- struct cmd_ds_802_11_afc afc;
- struct cmd_ds_802_11_led_ctrl ledgpio;
-
- struct cmd_tx_rate_query txrate;
- struct cmd_ds_bt_access bt;
- struct cmd_ds_fwt_access fwt;
- struct cmd_ds_get_tsf gettsf;
- struct cmd_ds_802_11_beacon_control bcn_ctrl;
- } params;
-} __attribute__ ((packed));
-
-#endif
+++ /dev/null
-/*
-
- Driver for the Marvell 8385 based compact flash WLAN cards.
-
- (C) 2007 by Holger Schurig <hs4233@mail.mn-solutions.de>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
-*/
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/moduleparam.h>
-#include <linux/firmware.h>
-#include <linux/netdevice.h>
-
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include <linux/io.h>
-
-#define DRV_NAME "libertas_cs"
-
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-
-
-/********************************************************************/
-/* Module stuff */
-/********************************************************************/
-
-MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
-MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
-MODULE_LICENSE("GPL");
-
-
-
-/********************************************************************/
-/* Data structures */
-/********************************************************************/
-
-struct if_cs_card {
- struct pcmcia_device *p_dev;
- struct lbs_private *priv;
- void __iomem *iobase;
-};
-
-
-
-/********************************************************************/
-/* Hardware access */
-/********************************************************************/
-
-/* This define enables wrapper functions which allow you
- to dump all register accesses. You normally won't this,
- except for development */
-/* #define DEBUG_IO */
-
-#ifdef DEBUG_IO
-static int debug_output = 0;
-#else
-/* This way the compiler optimizes the printk's away */
-#define debug_output 0
-#endif
-
-static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg)
-{
- unsigned int val = ioread8(card->iobase + reg);
- if (debug_output)
- printk(KERN_INFO "inb %08x<%02x\n", reg, val);
- return val;
-}
-static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
-{
- unsigned int val = ioread16(card->iobase + reg);
- if (debug_output)
- printk(KERN_INFO "inw %08x<%04x\n", reg, val);
- return val;
-}
-static inline void if_cs_read16_rep(
- struct if_cs_card *card,
- uint reg,
- void *buf,
- unsigned long count)
-{
- if (debug_output)
- printk(KERN_INFO "insw %08x<(0x%lx words)\n",
- reg, count);
- ioread16_rep(card->iobase + reg, buf, count);
-}
-
-static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
-{
- if (debug_output)
- printk(KERN_INFO "outb %08x>%02x\n", reg, val);
- iowrite8(val, card->iobase + reg);
-}
-
-static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val)
-{
- if (debug_output)
- printk(KERN_INFO "outw %08x>%04x\n", reg, val);
- iowrite16(val, card->iobase + reg);
-}
-
-static inline void if_cs_write16_rep(
- struct if_cs_card *card,
- uint reg,
- void *buf,
- unsigned long count)
-{
- if (debug_output)
- printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
- reg, count);
- iowrite16_rep(card->iobase + reg, buf, count);
-}
-
-
-/*
- * I know that polling/delaying is frowned upon. However, this procedure
- * with polling is needed while downloading the firmware. At this stage,
- * the hardware does unfortunately not create any interrupts.
- *
- * Fortunately, this function is never used once the firmware is in
- * the card. :-)
- *
- * As a reference, see the "Firmware Specification v5.1", page 18
- * and 19. I did not follow their suggested timing to the word,
- * but this works nice & fast anyway.
- */
-static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 reg)
-{
- int i;
-
- for (i = 0; i < 1000; i++) {
- u8 val = if_cs_read8(card, addr);
- if (val == reg)
- return i;
- udelay(500);
- }
- return -ETIME;
-}
-
-
-
-/* Host control registers and their bit definitions */
-
-#define IF_CS_H_STATUS 0x00000000
-#define IF_CS_H_STATUS_TX_OVER 0x0001
-#define IF_CS_H_STATUS_RX_OVER 0x0002
-#define IF_CS_H_STATUS_DNLD_OVER 0x0004
-
-#define IF_CS_H_INT_CAUSE 0x00000002
-#define IF_CS_H_IC_TX_OVER 0x0001
-#define IF_CS_H_IC_RX_OVER 0x0002
-#define IF_CS_H_IC_DNLD_OVER 0x0004
-#define IF_CS_H_IC_POWER_DOWN 0x0008
-#define IF_CS_H_IC_HOST_EVENT 0x0010
-#define IF_CS_H_IC_MASK 0x001f
-
-#define IF_CS_H_INT_MASK 0x00000004
-#define IF_CS_H_IM_MASK 0x001f
-
-#define IF_CS_H_WRITE_LEN 0x00000014
-
-#define IF_CS_H_WRITE 0x00000016
-
-#define IF_CS_H_CMD_LEN 0x00000018
-
-#define IF_CS_H_CMD 0x0000001A
-
-#define IF_CS_C_READ_LEN 0x00000024
-
-#define IF_CS_H_READ 0x00000010
-
-/* Card control registers and their bit definitions */
-
-#define IF_CS_C_STATUS 0x00000020
-#define IF_CS_C_S_TX_DNLD_RDY 0x0001
-#define IF_CS_C_S_RX_UPLD_RDY 0x0002
-#define IF_CS_C_S_CMD_DNLD_RDY 0x0004
-#define IF_CS_C_S_CMD_UPLD_RDY 0x0008
-#define IF_CS_C_S_CARDEVENT 0x0010
-#define IF_CS_C_S_MASK 0x001f
-#define IF_CS_C_S_STATUS_MASK 0x7f00
-
-#define IF_CS_C_INT_CAUSE 0x00000022
-#define IF_CS_C_IC_MASK 0x001f
-
-#define IF_CS_C_SQ_READ_LOW 0x00000028
-#define IF_CS_C_SQ_HELPER_OK 0x10
-
-#define IF_CS_C_CMD_LEN 0x00000030
-
-#define IF_CS_C_CMD 0x00000012
-
-#define IF_CS_SCRATCH 0x0000003F
-
-
-
-/********************************************************************/
-/* I/O */
-/********************************************************************/
-
-/*
- * Called from if_cs_host_to_card to send a command to the hardware
- */
-static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
-{
- struct if_cs_card *card = (struct if_cs_card *)priv->card;
- int ret = -1;
- int loops = 0;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- /* Is hardware ready? */
- while (1) {
- u16 val = if_cs_read16(card, IF_CS_C_STATUS);
- if (val & IF_CS_C_S_CMD_DNLD_RDY)
- break;
- if (++loops > 100) {
- lbs_pr_err("card not ready for commands\n");
- goto done;
- }
- mdelay(1);
- }
-
- if_cs_write16(card, IF_CS_H_CMD_LEN, nb);
-
- if_cs_write16_rep(card, IF_CS_H_CMD, buf, nb / 2);
- /* Are we supposed to transfer an odd amount of bytes? */
- if (nb & 1)
- if_cs_write8(card, IF_CS_H_CMD, buf[nb-1]);
-
- /* "Assert the download over interrupt command in the Host
- * status register" */
- if_cs_write16(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER);
-
- /* "Assert the download over interrupt command in the Card
- * interrupt case register" */
- if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER);
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
- return ret;
-}
-
-
-/*
- * Called from if_cs_host_to_card to send a data to the hardware
- */
-static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
-{
- struct if_cs_card *card = (struct if_cs_card *)priv->card;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- if_cs_write16(card, IF_CS_H_WRITE_LEN, nb);
-
- /* write even number of bytes, then odd byte if necessary */
- if_cs_write16_rep(card, IF_CS_H_WRITE, buf, nb / 2);
- if (nb & 1)
- if_cs_write8(card, IF_CS_H_WRITE, buf[nb-1]);
-
- if_cs_write16(card, IF_CS_H_STATUS, IF_CS_H_STATUS_TX_OVER);
- if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_STATUS_TX_OVER);
-
- lbs_deb_leave(LBS_DEB_CS);
-}
-
-
-/*
- * Get the command result out of the card.
- */
-static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
-{
- unsigned long flags;
- int ret = -1;
- u16 val;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- /* is hardware ready? */
- val = if_cs_read16(priv->card, IF_CS_C_STATUS);
- if ((val & IF_CS_C_S_CMD_UPLD_RDY) == 0) {
- lbs_pr_err("card not ready for CMD\n");
- goto out;
- }
-
- *len = if_cs_read16(priv->card, IF_CS_C_CMD_LEN);
- if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) {
- lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len);
- goto out;
- }
-
- /* read even number of bytes, then odd byte if necessary */
- if_cs_read16_rep(priv->card, IF_CS_C_CMD, data, *len/sizeof(u16));
- if (*len & 1)
- data[*len-1] = if_cs_read8(priv->card, IF_CS_C_CMD);
-
- /* This is a workaround for a firmware that reports too much
- * bytes */
- *len -= 8;
- ret = 0;
-
- /* Clear this flag again */
- spin_lock_irqsave(&priv->driver_lock, flags);
- priv->dnld_sent = DNLD_RES_RECEIVED;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
- return ret;
-}
-
-
-static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
-{
- struct sk_buff *skb = NULL;
- u16 len;
- u8 *data;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- len = if_cs_read16(priv->card, IF_CS_C_READ_LEN);
- if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
- lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len);
- priv->stats.rx_dropped++;
- goto dat_err;
- }
-
- skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
- if (!skb)
- goto out;
- skb_put(skb, len);
- skb_reserve(skb, 2);/* 16 byte align */
- data = skb->data;
-
- /* read even number of bytes, then odd byte if necessary */
- if_cs_read16_rep(priv->card, IF_CS_H_READ, data, len/sizeof(u16));
- if (len & 1)
- data[len-1] = if_cs_read8(priv->card, IF_CS_H_READ);
-
-dat_err:
- if_cs_write16(priv->card, IF_CS_H_STATUS, IF_CS_H_STATUS_RX_OVER);
- if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_RX_OVER);
-
-out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb);
- return skb;
-}
-
-
-
-/********************************************************************/
-/* Interrupts */
-/********************************************************************/
-
-static inline void if_cs_enable_ints(struct if_cs_card *card)
-{
- lbs_deb_enter(LBS_DEB_CS);
- if_cs_write16(card, IF_CS_H_INT_MASK, 0);
-}
-
-static inline void if_cs_disable_ints(struct if_cs_card *card)
-{
- lbs_deb_enter(LBS_DEB_CS);
- if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
-}
-
-
-static irqreturn_t if_cs_interrupt(int irq, void *data)
-{
- struct if_cs_card *card = data;
- struct lbs_private *priv = card->priv;
- u16 cause;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
- if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK);
-
- lbs_deb_cs("cause 0x%04x\n", cause);
- if (cause == 0) {
- /* Not for us */
- return IRQ_NONE;
- }
-
- if (cause == 0xffff) {
- /* Read in junk, the card has probably been removed */
- card->priv->surpriseremoved = 1;
- return IRQ_HANDLED;
- }
-
- /* TODO: I'm not sure what the best ordering is */
-
- cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
-
- if (cause & IF_CS_C_S_RX_UPLD_RDY) {
- struct sk_buff *skb;
- lbs_deb_cs("rx packet\n");
- skb = if_cs_receive_data(priv);
- if (skb)
- lbs_process_rxed_packet(priv, skb);
- }
-
- if (cause & IF_CS_H_IC_TX_OVER) {
- lbs_deb_cs("tx over\n");
- lbs_host_to_card_done(priv);
- }
-
- if (cause & IF_CS_C_S_CMD_UPLD_RDY) {
- unsigned long flags;
- u8 i;
-
- lbs_deb_cs("cmd upload ready\n");
- spin_lock_irqsave(&priv->driver_lock, flags);
- i = (priv->resp_idx == 0) ? 1 : 0;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- BUG_ON(priv->resp_len[i]);
- if_cs_receive_cmdres(priv, priv->resp_buf[i],
- &priv->resp_len[i]);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- lbs_notify_command_response(priv, i);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- }
-
- if (cause & IF_CS_H_IC_HOST_EVENT) {
- u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS)
- & IF_CS_C_S_STATUS_MASK;
- if_cs_write16(priv->card, IF_CS_H_INT_CAUSE,
- IF_CS_H_IC_HOST_EVENT);
- lbs_deb_cs("eventcause 0x%04x\n", event);
- lbs_queue_event(priv, event >> 8 & 0xff);
- }
-
- return IRQ_HANDLED;
-}
-
-
-
-
-/********************************************************************/
-/* Firmware */
-/********************************************************************/
-
-/*
- * Tries to program the helper firmware.
- *
- * Return 0 on success
- */
-static int if_cs_prog_helper(struct if_cs_card *card)
-{
- int ret = 0;
- int sent = 0;
- u8 scratch;
- const struct firmware *fw;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- scratch = if_cs_read8(card, IF_CS_SCRATCH);
-
- /* "If the value is 0x5a, the firmware is already
- * downloaded successfully"
- */
- if (scratch == 0x5a)
- goto done;
-
- /* "If the value is != 00, it is invalid value of register */
- if (scratch != 0x00) {
- ret = -ENODEV;
- goto done;
- }
-
- /* TODO: make firmware file configurable */
- ret = request_firmware(&fw, "libertas_cs_helper.fw",
- &handle_to_dev(card->p_dev));
- if (ret) {
- lbs_pr_err("can't load helper firmware\n");
- ret = -ENODEV;
- goto done;
- }
- lbs_deb_cs("helper size %td\n", fw->size);
-
- /* "Set the 5 bytes of the helper image to 0" */
- /* Not needed, this contains an ARM branch instruction */
-
- for (;;) {
- /* "the number of bytes to send is 256" */
- int count = 256;
- int remain = fw->size - sent;
-
- if (remain < count)
- count = remain;
-
- /* "write the number of bytes to be sent to the I/O Command
- * write length register" */
- if_cs_write16(card, IF_CS_H_CMD_LEN, count);
-
- /* "write this to I/O Command port register as 16 bit writes */
- if (count)
- if_cs_write16_rep(card, IF_CS_H_CMD,
- &fw->data[sent],
- count >> 1);
-
- /* "Assert the download over interrupt command in the Host
- * status register" */
- if_cs_write8(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER);
-
- /* "Assert the download over interrupt command in the Card
- * interrupt case register" */
- if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER);
-
- /* "The host polls the Card Status register ... for 50 ms before
- declaring a failure */
- ret = if_cs_poll_while_fw_download(card, IF_CS_C_STATUS,
- IF_CS_C_S_CMD_DNLD_RDY);
- if (ret < 0) {
- lbs_pr_err("can't download helper at 0x%x, ret %d\n",
- sent, ret);
- goto done;
- }
-
- if (count == 0)
- break;
-
- sent += count;
- }
-
- release_firmware(fw);
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
- return ret;
-}
-
-
-static int if_cs_prog_real(struct if_cs_card *card)
-{
- const struct firmware *fw;
- int ret = 0;
- int retry = 0;
- int len = 0;
- int sent;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- /* TODO: make firmware file configurable */
- ret = request_firmware(&fw, "libertas_cs.fw",
- &handle_to_dev(card->p_dev));
- if (ret) {
- lbs_pr_err("can't load firmware\n");
- ret = -ENODEV;
- goto done;
- }
- lbs_deb_cs("fw size %td\n", fw->size);
-
- ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK);
- if (ret < 0) {
- lbs_pr_err("helper firmware doesn't answer\n");
- goto err_release;
- }
-
- for (sent = 0; sent < fw->size; sent += len) {
- len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW);
- if (len & 1) {
- retry++;
- lbs_pr_info("odd, need to retry this firmware block\n");
- } else {
- retry = 0;
- }
-
- if (retry > 20) {
- lbs_pr_err("could not download firmware\n");
- ret = -ENODEV;
- goto err_release;
- }
- if (retry) {
- sent -= len;
- }
-
-
- if_cs_write16(card, IF_CS_H_CMD_LEN, len);
-
- if_cs_write16_rep(card, IF_CS_H_CMD,
- &fw->data[sent],
- (len+1) >> 1);
- if_cs_write8(card, IF_CS_H_STATUS, IF_CS_H_STATUS_DNLD_OVER);
- if_cs_write16(card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_DNLD_OVER);
-
- ret = if_cs_poll_while_fw_download(card, IF_CS_C_STATUS,
- IF_CS_C_S_CMD_DNLD_RDY);
- if (ret < 0) {
- lbs_pr_err("can't download firmware at 0x%x\n", sent);
- goto err_release;
- }
- }
-
- ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
- if (ret < 0) {
- lbs_pr_err("firmware download failed\n");
- goto err_release;
- }
-
- ret = 0;
- goto done;
-
-
-err_release:
- release_firmware(fw);
-
-done:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
- return ret;
-}
-
-
-
-/********************************************************************/
-/* Callback functions for libertas.ko */
-/********************************************************************/
-
-/* Send commands or data packets to the card */
-static int if_cs_host_to_card(struct lbs_private *priv,
- u8 type,
- u8 *buf,
- u16 nb)
-{
- int ret = -1;
-
- lbs_deb_enter_args(LBS_DEB_CS, "type %d, bytes %d", type, nb);
-
- switch (type) {
- case MVMS_DAT:
- priv->dnld_sent = DNLD_DATA_SENT;
- if_cs_send_data(priv, buf, nb);
- ret = 0;
- break;
- case MVMS_CMD:
- priv->dnld_sent = DNLD_CMD_SENT;
- ret = if_cs_send_cmd(priv, buf, nb);
- break;
- default:
- lbs_pr_err("%s: unsupported type %d\n", __FUNCTION__, type);
- }
-
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
- return ret;
-}
-
-
-/********************************************************************/
-/* Card Services */
-/********************************************************************/
-
-/*
- * After a card is removed, if_cs_release() will unregister the
- * device, and release the PCMCIA configuration. If the device is
- * still open, this will be postponed until it is closed.
- */
-static void if_cs_release(struct pcmcia_device *p_dev)
-{
- struct if_cs_card *card = p_dev->priv;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- free_irq(p_dev->irq.AssignedIRQ, card);
- pcmcia_disable_device(p_dev);
- if (card->iobase)
- ioport_unmap(card->iobase);
-
- lbs_deb_leave(LBS_DEB_CS);
-}
-
-
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device. The device is registered with Card
- * Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a card
- * insertion event.
- */
-static int if_cs_probe(struct pcmcia_device *p_dev)
-{
- int ret = -ENOMEM;
- struct lbs_private *priv;
- struct if_cs_card *card;
- /* CIS parsing */
- tuple_t tuple;
- cisparse_t parse;
- cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
- cistpl_io_t *io = &cfg->io;
- u_char buf[64];
-
- lbs_deb_enter(LBS_DEB_CS);
-
- card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL);
- if (!card) {
- lbs_pr_err("error in kzalloc\n");
- goto out;
- }
- card->p_dev = p_dev;
- p_dev->priv = card;
-
- p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
- p_dev->irq.Handler = NULL;
- p_dev->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
-
- p_dev->conf.Attributes = 0;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
-
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 ||
- (ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 ||
- (ret = pcmcia_parse_tuple(p_dev, &tuple, &parse)) != 0)
- {
- lbs_pr_err("error in pcmcia_get_first_tuple etc\n");
- goto out1;
- }
-
- p_dev->conf.ConfigIndex = cfg->index;
-
- /* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1) {
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
- }
-
- /* IO window settings */
- if (cfg->io.nwin != 1) {
- lbs_pr_err("wrong CIS (check number of IO windows)\n");
- ret = -ENODEV;
- goto out1;
- }
- p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- p_dev->io.BasePort1 = io->win[0].base;
- p_dev->io.NumPorts1 = io->win[0].len;
-
- /* This reserves IO space but doesn't actually enable it */
- ret = pcmcia_request_io(p_dev, &p_dev->io);
- if (ret) {
- lbs_pr_err("error in pcmcia_request_io\n");
- goto out1;
- }
-
- /*
- * Allocate an interrupt line. Note that this does not assign
- * a handler to the interrupt, unless the 'Handler' member of
- * the irq structure is initialized.
- */
- if (p_dev->conf.Attributes & CONF_ENABLE_IRQ) {
- ret = pcmcia_request_irq(p_dev, &p_dev->irq);
- if (ret) {
- lbs_pr_err("error in pcmcia_request_irq\n");
- goto out1;
- }
- }
-
- /* Initialize io access */
- card->iobase = ioport_map(p_dev->io.BasePort1, p_dev->io.NumPorts1);
- if (!card->iobase) {
- lbs_pr_err("error in ioport_map\n");
- ret = -EIO;
- goto out1;
- }
-
- /*
- * This actually configures the PCMCIA socket -- setting up
- * the I/O windows and the interrupt mapping, and putting the
- * card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
- if (ret) {
- lbs_pr_err("error in pcmcia_request_configuration\n");
- goto out2;
- }
-
- /* Finally, report what we've done */
- lbs_deb_cs("irq %d, io 0x%04x-0x%04x\n",
- p_dev->irq.AssignedIRQ, p_dev->io.BasePort1,
- p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1);
-
-
- /* Load the firmware early, before calling into libertas.ko */
- ret = if_cs_prog_helper(card);
- if (ret == 0)
- ret = if_cs_prog_real(card);
- if (ret)
- goto out2;
-
- /* Make this card known to the libertas driver */
- priv = lbs_add_card(card, &p_dev->dev);
- if (!priv) {
- ret = -ENOMEM;
- goto out2;
- }
-
- /* Finish setting up fields in lbs_private */
- card->priv = priv;
- priv->card = card;
- priv->hw_host_to_card = if_cs_host_to_card;
- priv->fw_ready = 1;
-
- /* Now actually get the IRQ */
- ret = request_irq(p_dev->irq.AssignedIRQ, if_cs_interrupt,
- IRQF_SHARED, DRV_NAME, card);
- if (ret) {
- lbs_pr_err("error in request_irq\n");
- goto out3;
- }
-
- /* Clear any interrupt cause that happend while sending
- * firmware/initializing card */
- if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK);
- if_cs_enable_ints(card);
-
- /* And finally bring the card up */
- if (lbs_start_card(priv) != 0) {
- lbs_pr_err("could not activate card\n");
- goto out3;
- }
-
- /* The firmware for the CF card supports powersave */
- priv->ps_supported = 1;
-
- ret = 0;
- goto out;
-
-out3:
- lbs_remove_card(priv);
-out2:
- ioport_unmap(card->iobase);
-out1:
- pcmcia_disable_device(p_dev);
-out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
- return ret;
-}
-
-
-/*
- * This deletes a driver "instance". The device is de-registered with
- * Card Services. If it has been released, all local data structures
- * are freed. Otherwise, the structures will be freed when the device
- * is released.
- */
-static void if_cs_detach(struct pcmcia_device *p_dev)
-{
- struct if_cs_card *card = p_dev->priv;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- lbs_stop_card(card->priv);
- lbs_remove_card(card->priv);
- if_cs_disable_ints(card);
- if_cs_release(p_dev);
- kfree(card);
-
- lbs_deb_leave(LBS_DEB_CS);
-}
-
-
-
-/********************************************************************/
-/* Module initialization */
-/********************************************************************/
-
-static struct pcmcia_device_id if_cs_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x02df, 0x8103),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
-
-
-static struct pcmcia_driver lbs_driver = {
- .owner = THIS_MODULE,
- .drv = {
- .name = DRV_NAME,
- },
- .probe = if_cs_probe,
- .remove = if_cs_detach,
- .id_table = if_cs_ids,
-};
-
-
-static int __init if_cs_init(void)
-{
- int ret;
-
- lbs_deb_enter(LBS_DEB_CS);
- ret = pcmcia_register_driver(&lbs_driver);
- lbs_deb_leave(LBS_DEB_CS);
- return ret;
-}
-
-
-static void __exit if_cs_exit(void)
-{
- lbs_deb_enter(LBS_DEB_CS);
- pcmcia_unregister_driver(&lbs_driver);
- lbs_deb_leave(LBS_DEB_CS);
-}
-
-
-module_init(if_cs_init);
-module_exit(if_cs_exit);
+++ /dev/null
-/*
- * linux/drivers/net/wireless/libertas/if_sdio.c
- *
- * Copyright 2007 Pierre Ossman
- *
- * Inspired by if_cs.c, Copyright 2007 Holger Schurig
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This hardware has more or less no CMD53 support, so all registers
- * must be accessed using sdio_readb()/sdio_writeb().
- *
- * Transfers must be in one transaction or the firmware goes bonkers.
- * This means that the transfer must either be small enough to do a
- * byte based transfer or it must be padded to a multiple of the
- * current block size.
- *
- * As SDIO is still new to the kernel, it is unfortunately common with
- * bugs in the host controllers related to that. One such bug is that
- * controllers cannot do transfers that aren't a multiple of 4 bytes.
- * If you don't have time to fix the host controller driver, you can
- * work around the problem by modifying if_sdio_host_to_card() and
- * if_sdio_card_to_host() to pad the data.
- */
-
-#include <linux/moduleparam.h>
-#include <linux/firmware.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-
-#include "host.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "if_sdio.h"
-
-static char *lbs_helper_name = NULL;
-module_param_named(helper_name, lbs_helper_name, charp, 0644);
-
-static char *lbs_fw_name = NULL;
-module_param_named(fw_name, lbs_fw_name, charp, 0644);
-
-static const struct sdio_device_id if_sdio_ids[] = {
- { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
- { /* end: all zeroes */ },
-};
-
-MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
-
-struct if_sdio_model {
- int model;
- const char *helper;
- const char *firmware;
-};
-
-static struct if_sdio_model if_sdio_models[] = {
- {
- /* 8385 */
- .model = 0x04,
- .helper = "sd8385_helper.bin",
- .firmware = "sd8385.bin",
- },
- {
- /* 8686 */
- .model = 0x0B,
- .helper = "sd8686_helper.bin",
- .firmware = "sd8686.bin",
- },
-};
-
-struct if_sdio_packet {
- struct if_sdio_packet *next;
- u16 nb;
- u8 buffer[0] __attribute__((aligned(4)));
-};
-
-struct if_sdio_card {
- struct sdio_func *func;
- struct lbs_private *priv;
-
- int model;
- unsigned long ioport;
-
- const char *helper;
- const char *firmware;
-
- u8 buffer[65536];
-
- spinlock_t lock;
- struct if_sdio_packet *packets;
- struct work_struct packet_worker;
-};
-
-/********************************************************************/
-/* I/O */
-/********************************************************************/
-
-static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
-{
- int ret, reg;
- u16 scratch;
-
- if (card->model == 0x04)
- reg = IF_SDIO_SCRATCH_OLD;
- else
- reg = IF_SDIO_SCRATCH;
-
- scratch = sdio_readb(card->func, reg, &ret);
- if (!ret)
- scratch |= sdio_readb(card->func, reg + 1, &ret) << 8;
-
- if (err)
- *err = ret;
-
- if (ret)
- return 0xffff;
-
- return scratch;
-}
-
-static int if_sdio_handle_cmd(struct if_sdio_card *card,
- u8 *buffer, unsigned size)
-{
- struct lbs_private *priv = card->priv;
- int ret;
- unsigned long flags;
- u8 i;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- if (size > LBS_CMD_BUFFER_SIZE) {
- lbs_deb_sdio("response packet too large (%d bytes)\n",
- (int)size);
- ret = -E2BIG;
- goto out;
- }
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- i = (priv->resp_idx == 0) ? 1 : 0;
- BUG_ON(priv->resp_len[i]);
- priv->resp_len[i] = size;
- memcpy(priv->resp_buf[i], buffer, size);
- lbs_notify_command_response(priv, i);
-
- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
-
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
- return ret;
-}
-
-static int if_sdio_handle_data(struct if_sdio_card *card,
- u8 *buffer, unsigned size)
-{
- int ret;
- struct sk_buff *skb;
- char *data;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
- lbs_deb_sdio("response packet too large (%d bytes)\n",
- (int)size);
- ret = -E2BIG;
- goto out;
- }
-
- skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN);
- if (!skb) {
- ret = -ENOMEM;
- goto out;
- }
-
- skb_reserve(skb, NET_IP_ALIGN);
-
- data = skb_put(skb, size);
-
- memcpy(data, buffer, size);
-
- lbs_process_rxed_packet(card->priv, skb);
-
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-static int if_sdio_handle_event(struct if_sdio_card *card,
- u8 *buffer, unsigned size)
-{
- int ret;
- u32 event;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- if (card->model == 0x04) {
- event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
- if (ret)
- goto out;
- } else {
- if (size < 4) {
- lbs_deb_sdio("event packet too small (%d bytes)\n",
- (int)size);
- ret = -EINVAL;
- goto out;
- }
- event = buffer[3] << 24;
- event |= buffer[2] << 16;
- event |= buffer[1] << 8;
- event |= buffer[0] << 0;
- }
-
- lbs_queue_event(card->priv, event & 0xFF);
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-static int if_sdio_card_to_host(struct if_sdio_card *card)
-{
- int ret;
- u8 status;
- u16 size, type, chunk;
- unsigned long timeout;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- size = if_sdio_read_scratch(card, &ret);
- if (ret)
- goto out;
-
- if (size < 4) {
- lbs_deb_sdio("invalid packet size (%d bytes) from firmware\n",
- (int)size);
- ret = -EINVAL;
- goto out;
- }
-
- timeout = jiffies + HZ;
- while (1) {
- status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
- if (ret)
- goto out;
- if (status & IF_SDIO_IO_RDY)
- break;
- if (time_after(jiffies, timeout)) {
- ret = -ETIMEDOUT;
- goto out;
- }
- mdelay(1);
- }
-
- /*
- * The transfer must be in one transaction or the firmware
- * goes suicidal.
- */
- chunk = size;
- if ((chunk > card->func->cur_blksize) || (chunk > 512)) {
- chunk = (chunk + card->func->cur_blksize - 1) /
- card->func->cur_blksize * card->func->cur_blksize;
- }
-
- ret = sdio_readsb(card->func, card->buffer, card->ioport, chunk);
- if (ret)
- goto out;
-
- chunk = card->buffer[0] | (card->buffer[1] << 8);
- type = card->buffer[2] | (card->buffer[3] << 8);
-
- lbs_deb_sdio("packet of type %d and size %d bytes\n",
- (int)type, (int)chunk);
-
- if (chunk > size) {
- lbs_deb_sdio("packet fragment (%d > %d)\n",
- (int)chunk, (int)size);
- ret = -EINVAL;
- goto out;
- }
-
- if (chunk < size) {
- lbs_deb_sdio("packet fragment (%d < %d)\n",
- (int)chunk, (int)size);
- }
-
- switch (type) {
- case MVMS_CMD:
- ret = if_sdio_handle_cmd(card, card->buffer + 4, chunk - 4);
- if (ret)
- goto out;
- break;
- case MVMS_DAT:
- ret = if_sdio_handle_data(card, card->buffer + 4, chunk - 4);
- if (ret)
- goto out;
- break;
- case MVMS_EVENT:
- ret = if_sdio_handle_event(card, card->buffer + 4, chunk - 4);
- if (ret)
- goto out;
- break;
- default:
- lbs_deb_sdio("invalid type (%d) from firmware\n",
- (int)type);
- ret = -EINVAL;
- goto out;
- }
-
-out:
- if (ret)
- lbs_pr_err("problem fetching packet from firmware\n");
-
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-static void if_sdio_host_to_card_worker(struct work_struct *work)
-{
- struct if_sdio_card *card;
- struct if_sdio_packet *packet;
- unsigned long timeout;
- u8 status;
- int ret;
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- card = container_of(work, struct if_sdio_card, packet_worker);
-
- while (1) {
- spin_lock_irqsave(&card->lock, flags);
- packet = card->packets;
- if (packet)
- card->packets = packet->next;
- spin_unlock_irqrestore(&card->lock, flags);
-
- if (!packet)
- break;
-
- sdio_claim_host(card->func);
-
- timeout = jiffies + HZ;
- while (1) {
- status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
- if (ret)
- goto release;
- if (status & IF_SDIO_IO_RDY)
- break;
- if (time_after(jiffies, timeout)) {
- ret = -ETIMEDOUT;
- goto release;
- }
- mdelay(1);
- }
-
- ret = sdio_writesb(card->func, card->ioport,
- packet->buffer, packet->nb);
- if (ret)
- goto release;
-release:
- sdio_release_host(card->func);
-
- kfree(packet);
- }
-
- lbs_deb_leave(LBS_DEB_SDIO);
-}
-
-/********************************************************************/
-/* Firmware */
-/********************************************************************/
-
-static int if_sdio_prog_helper(struct if_sdio_card *card)
-{
- int ret;
- u8 status;
- const struct firmware *fw;
- unsigned long timeout;
- u8 *chunk_buffer;
- u32 chunk_size;
- u8 *firmware;
- size_t size;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- ret = request_firmware(&fw, card->helper, &card->func->dev);
- if (ret) {
- lbs_pr_err("can't load helper firmware\n");
- goto out;
- }
-
- chunk_buffer = kzalloc(64, GFP_KERNEL);
- if (!chunk_buffer) {
- ret = -ENOMEM;
- goto release_fw;
- }
-
- sdio_claim_host(card->func);
-
- ret = sdio_set_block_size(card->func, 32);
- if (ret)
- goto release;
-
- firmware = fw->data;
- size = fw->size;
-
- while (size) {
- timeout = jiffies + HZ;
- while (1) {
- status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
- if (ret)
- goto release;
- if ((status & IF_SDIO_IO_RDY) &&
- (status & IF_SDIO_DL_RDY))
- break;
- if (time_after(jiffies, timeout)) {
- ret = -ETIMEDOUT;
- goto release;
- }
- mdelay(1);
- }
-
- chunk_size = min(size, (size_t)60);
-
- *((__le32*)chunk_buffer) = cpu_to_le32(chunk_size);
- memcpy(chunk_buffer + 4, firmware, chunk_size);
-/*
- lbs_deb_sdio("sending %d bytes chunk\n", chunk_size);
-*/
- ret = sdio_writesb(card->func, card->ioport,
- chunk_buffer, 64);
- if (ret)
- goto release;
-
- firmware += chunk_size;
- size -= chunk_size;
- }
-
- /* an empty block marks the end of the transfer */
- memset(chunk_buffer, 0, 4);
- ret = sdio_writesb(card->func, card->ioport, chunk_buffer, 64);
- if (ret)
- goto release;
-
- lbs_deb_sdio("waiting for helper to boot...\n");
-
- /* wait for the helper to boot by looking at the size register */
- timeout = jiffies + HZ;
- while (1) {
- u16 req_size;
-
- req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
- if (ret)
- goto release;
-
- req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
- if (ret)
- goto release;
-
- if (req_size != 0)
- break;
-
- if (time_after(jiffies, timeout)) {
- ret = -ETIMEDOUT;
- goto release;
- }
-
- msleep(10);
- }
-
- ret = 0;
-
-release:
- sdio_set_block_size(card->func, 0);
- sdio_release_host(card->func);
- kfree(chunk_buffer);
-release_fw:
- release_firmware(fw);
-
-out:
- if (ret)
- lbs_pr_err("failed to load helper firmware\n");
-
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-static int if_sdio_prog_real(struct if_sdio_card *card)
-{
- int ret;
- u8 status;
- const struct firmware *fw;
- unsigned long timeout;
- u8 *chunk_buffer;
- u32 chunk_size;
- u8 *firmware;
- size_t size, req_size;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- ret = request_firmware(&fw, card->firmware, &card->func->dev);
- if (ret) {
- lbs_pr_err("can't load firmware\n");
- goto out;
- }
-
- chunk_buffer = kzalloc(512, GFP_KERNEL);
- if (!chunk_buffer) {
- ret = -ENOMEM;
- goto release_fw;
- }
-
- sdio_claim_host(card->func);
-
- ret = sdio_set_block_size(card->func, 32);
- if (ret)
- goto release;
-
- firmware = fw->data;
- size = fw->size;
-
- while (size) {
- timeout = jiffies + HZ;
- while (1) {
- status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
- if (ret)
- goto release;
- if ((status & IF_SDIO_IO_RDY) &&
- (status & IF_SDIO_DL_RDY))
- break;
- if (time_after(jiffies, timeout)) {
- ret = -ETIMEDOUT;
- goto release;
- }
- mdelay(1);
- }
-
- req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
- if (ret)
- goto release;
-
- req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
- if (ret)
- goto release;
-/*
- lbs_deb_sdio("firmware wants %d bytes\n", (int)req_size);
-*/
- if (req_size == 0) {
- lbs_deb_sdio("firmware helper gave up early\n");
- ret = -EIO;
- goto release;
- }
-
- if (req_size & 0x01) {
- lbs_deb_sdio("firmware helper signalled error\n");
- ret = -EIO;
- goto release;
- }
-
- if (req_size > size)
- req_size = size;
-
- while (req_size) {
- chunk_size = min(req_size, (size_t)512);
-
- memcpy(chunk_buffer, firmware, chunk_size);
-/*
- lbs_deb_sdio("sending %d bytes (%d bytes) chunk\n",
- chunk_size, (chunk_size + 31) / 32 * 32);
-*/
- ret = sdio_writesb(card->func, card->ioport,
- chunk_buffer, (chunk_size + 31) / 32 * 32);
- if (ret)
- goto release;
-
- firmware += chunk_size;
- size -= chunk_size;
- req_size -= chunk_size;
- }
- }
-
- ret = 0;
-
- lbs_deb_sdio("waiting for firmware to boot...\n");
-
- /* wait for the firmware to boot */
- timeout = jiffies + HZ;
- while (1) {
- u16 scratch;
-
- scratch = if_sdio_read_scratch(card, &ret);
- if (ret)
- goto release;
-
- if (scratch == IF_SDIO_FIRMWARE_OK)
- break;
-
- if (time_after(jiffies, timeout)) {
- ret = -ETIMEDOUT;
- goto release;
- }
-
- msleep(10);
- }
-
- ret = 0;
-
-release:
- sdio_set_block_size(card->func, 0);
- sdio_release_host(card->func);
- kfree(chunk_buffer);
-release_fw:
- release_firmware(fw);
-
-out:
- if (ret)
- lbs_pr_err("failed to load firmware\n");
-
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-static int if_sdio_prog_firmware(struct if_sdio_card *card)
-{
- int ret;
- u16 scratch;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- sdio_claim_host(card->func);
- scratch = if_sdio_read_scratch(card, &ret);
- sdio_release_host(card->func);
-
- if (ret)
- goto out;
-
- if (scratch == IF_SDIO_FIRMWARE_OK) {
- lbs_deb_sdio("firmware already loaded\n");
- goto success;
- }
-
- ret = if_sdio_prog_helper(card);
- if (ret)
- goto out;
-
- ret = if_sdio_prog_real(card);
- if (ret)
- goto out;
-
-success:
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-/*******************************************************************/
-/* Libertas callbacks */
-/*******************************************************************/
-
-static int if_sdio_host_to_card(struct lbs_private *priv,
- u8 type, u8 *buf, u16 nb)
-{
- int ret;
- struct if_sdio_card *card;
- struct if_sdio_packet *packet, *cur;
- u16 size;
- unsigned long flags;
-
- lbs_deb_enter_args(LBS_DEB_SDIO, "type %d, bytes %d", type, nb);
-
- card = priv->card;
-
- if (nb > (65536 - sizeof(struct if_sdio_packet) - 4)) {
- ret = -EINVAL;
- goto out;
- }
-
- /*
- * The transfer must be in one transaction or the firmware
- * goes suicidal.
- */
- size = nb + 4;
- if ((size > card->func->cur_blksize) || (size > 512)) {
- size = (size + card->func->cur_blksize - 1) /
- card->func->cur_blksize * card->func->cur_blksize;
- }
-
- packet = kzalloc(sizeof(struct if_sdio_packet) + size,
- GFP_ATOMIC);
- if (!packet) {
- ret = -ENOMEM;
- goto out;
- }
-
- packet->next = NULL;
- packet->nb = size;
-
- /*
- * SDIO specific header.
- */
- packet->buffer[0] = (nb + 4) & 0xff;
- packet->buffer[1] = ((nb + 4) >> 8) & 0xff;
- packet->buffer[2] = type;
- packet->buffer[3] = 0;
-
- memcpy(packet->buffer + 4, buf, nb);
-
- spin_lock_irqsave(&card->lock, flags);
-
- if (!card->packets)
- card->packets = packet;
- else {
- cur = card->packets;
- while (cur->next)
- cur = cur->next;
- cur->next = packet;
- }
-
- switch (type) {
- case MVMS_CMD:
- priv->dnld_sent = DNLD_CMD_SENT;
- break;
- case MVMS_DAT:
- priv->dnld_sent = DNLD_DATA_SENT;
- break;
- default:
- lbs_deb_sdio("unknown packet type %d\n", (int)type);
- }
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- schedule_work(&card->packet_worker);
-
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-/*******************************************************************/
-/* SDIO callbacks */
-/*******************************************************************/
-
-static void if_sdio_interrupt(struct sdio_func *func)
-{
- int ret;
- struct if_sdio_card *card;
- u8 cause;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- card = sdio_get_drvdata(func);
-
- cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
- if (ret)
- goto out;
-
- lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
-
- sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret);
- if (ret)
- goto out;
-
- /*
- * Ignore the define name, this really means the card has
- * successfully received the command.
- */
- if (cause & IF_SDIO_H_INT_DNLD)
- lbs_host_to_card_done(card->priv);
-
-
- if (cause & IF_SDIO_H_INT_UPLD) {
- ret = if_sdio_card_to_host(card);
- if (ret)
- goto out;
- }
-
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-}
-
-static int if_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
-{
- struct if_sdio_card *card;
- struct lbs_private *priv;
- int ret, i;
- unsigned int model;
- struct if_sdio_packet *packet;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- for (i = 0;i < func->card->num_info;i++) {
- if (sscanf(func->card->info[i],
- "802.11 SDIO ID: %x", &model) == 1)
- break;
- if (sscanf(func->card->info[i],
- "ID: %x", &model) == 1)
- break;
- if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
- model = 4;
- break;
- }
- }
-
- if (i == func->card->num_info) {
- lbs_pr_err("unable to identify card model\n");
- return -ENODEV;
- }
-
- card = kzalloc(sizeof(struct if_sdio_card), GFP_KERNEL);
- if (!card)
- return -ENOMEM;
-
- card->func = func;
- card->model = model;
- spin_lock_init(&card->lock);
- INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
-
- for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
- if (card->model == if_sdio_models[i].model)
- break;
- }
-
- if (i == ARRAY_SIZE(if_sdio_models)) {
- lbs_pr_err("unkown card model 0x%x\n", card->model);
- ret = -ENODEV;
- goto free;
- }
-
- card->helper = if_sdio_models[i].helper;
- card->firmware = if_sdio_models[i].firmware;
-
- if (lbs_helper_name) {
- lbs_deb_sdio("overriding helper firmware: %s\n",
- lbs_helper_name);
- card->helper = lbs_helper_name;
- }
-
- if (lbs_fw_name) {
- lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name);
- card->firmware = lbs_fw_name;
- }
-
- sdio_claim_host(func);
-
- ret = sdio_enable_func(func);
- if (ret)
- goto release;
-
- ret = sdio_claim_irq(func, if_sdio_interrupt);
- if (ret)
- goto disable;
-
- card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
- if (ret)
- goto release_int;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
- if (ret)
- goto release_int;
-
- card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
- if (ret)
- goto release_int;
-
- sdio_release_host(func);
-
- sdio_set_drvdata(func, card);
-
- lbs_deb_sdio("class = 0x%X, vendor = 0x%X, "
- "device = 0x%X, model = 0x%X, ioport = 0x%X\n",
- func->class, func->vendor, func->device,
- model, (unsigned)card->ioport);
-
- ret = if_sdio_prog_firmware(card);
- if (ret)
- goto reclaim;
-
- priv = lbs_add_card(card, &func->dev);
- if (!priv) {
- ret = -ENOMEM;
- goto reclaim;
- }
-
- card->priv = priv;
-
- priv->card = card;
- priv->hw_host_to_card = if_sdio_host_to_card;
-
- priv->fw_ready = 1;
-
- /*
- * Enable interrupts now that everything is set up
- */
- sdio_claim_host(func);
- sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
- sdio_release_host(func);
- if (ret)
- goto reclaim;
-
- ret = lbs_start_card(priv);
- if (ret)
- goto err_activate_card;
-
-out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-
-err_activate_card:
- flush_scheduled_work();
- free_netdev(priv->dev);
- kfree(priv);
-reclaim:
- sdio_claim_host(func);
-release_int:
- sdio_release_irq(func);
-disable:
- sdio_disable_func(func);
-release:
- sdio_release_host(func);
-free:
- while (card->packets) {
- packet = card->packets;
- card->packets = card->packets->next;
- kfree(packet);
- }
-
- kfree(card);
-
- goto out;
-}
-
-static void if_sdio_remove(struct sdio_func *func)
-{
- struct if_sdio_card *card;
- struct if_sdio_packet *packet;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- card = sdio_get_drvdata(func);
-
- card->priv->surpriseremoved = 1;
-
- lbs_deb_sdio("call remove card\n");
- lbs_stop_card(card->priv);
- lbs_remove_card(card->priv);
-
- flush_scheduled_work();
-
- sdio_claim_host(func);
- sdio_release_irq(func);
- sdio_disable_func(func);
- sdio_release_host(func);
-
- while (card->packets) {
- packet = card->packets;
- card->packets = card->packets->next;
- kfree(packet);
- }
-
- kfree(card);
-
- lbs_deb_leave(LBS_DEB_SDIO);
-}
-
-static struct sdio_driver if_sdio_driver = {
- .name = "libertas_sdio",
- .id_table = if_sdio_ids,
- .probe = if_sdio_probe,
- .remove = if_sdio_remove,
-};
-
-/*******************************************************************/
-/* Module functions */
-/*******************************************************************/
-
-static int __init if_sdio_init_module(void)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n");
- printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n");
-
- ret = sdio_register_driver(&if_sdio_driver);
-
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
- return ret;
-}
-
-static void __exit if_sdio_exit_module(void)
-{
- lbs_deb_enter(LBS_DEB_SDIO);
-
- sdio_unregister_driver(&if_sdio_driver);
-
- lbs_deb_leave(LBS_DEB_SDIO);
-}
-
-module_init(if_sdio_init_module);
-module_exit(if_sdio_exit_module);
-
-MODULE_DESCRIPTION("Libertas SDIO WLAN Driver");
-MODULE_AUTHOR("Pierre Ossman");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * linux/drivers/net/wireless/libertas/if_sdio.h
- *
- * Copyright 2007 Pierre Ossman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef _LBS_IF_SDIO_H
-#define _LBS_IF_SDIO_H
-
-#define IF_SDIO_IOPORT 0x00
-
-#define IF_SDIO_H_INT_MASK 0x04
-#define IF_SDIO_H_INT_OFLOW 0x08
-#define IF_SDIO_H_INT_UFLOW 0x04
-#define IF_SDIO_H_INT_DNLD 0x02
-#define IF_SDIO_H_INT_UPLD 0x01
-
-#define IF_SDIO_H_INT_STATUS 0x05
-#define IF_SDIO_H_INT_RSR 0x06
-#define IF_SDIO_H_INT_STATUS2 0x07
-
-#define IF_SDIO_RD_BASE 0x10
-
-#define IF_SDIO_STATUS 0x20
-#define IF_SDIO_IO_RDY 0x08
-#define IF_SDIO_CIS_RDY 0x04
-#define IF_SDIO_UL_RDY 0x02
-#define IF_SDIO_DL_RDY 0x01
-
-#define IF_SDIO_C_INT_MASK 0x24
-#define IF_SDIO_C_INT_STATUS 0x28
-#define IF_SDIO_C_INT_RSR 0x2C
-
-#define IF_SDIO_SCRATCH 0x34
-#define IF_SDIO_SCRATCH_OLD 0x80fe
-#define IF_SDIO_FIRMWARE_OK 0xfedc
-
-#define IF_SDIO_EVENT 0x80fc
-
-#endif
+++ /dev/null
-/**
- * This file contains functions used in USB interface module.
- */
-#include <linux/delay.h>
-#include <linux/moduleparam.h>
-#include <linux/firmware.h>
-#include <linux/netdevice.h>
-#include <linux/usb.h>
-#ifdef CONFIG_OLPC
-#include <asm/olpc.h>
-#endif
-
-#define DRV_NAME "usb8xxx"
-
-#include "host.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "cmd.h"
-#include "if_usb.h"
-
-#define INSANEDEBUG 0
-#define lbs_deb_usb2(...) do { if (INSANEDEBUG) lbs_deb_usbd(__VA_ARGS__); } while (0)
-
-#define MESSAGE_HEADER_LEN 4
-
-static char *lbs_fw_name = "usb8388.bin";
-module_param_named(fw_name, lbs_fw_name, charp, 0644);
-
-static struct usb_device_id if_usb_table[] = {
- /* Enter the device signature inside */
- { USB_DEVICE(0x1286, 0x2001) },
- { USB_DEVICE(0x05a3, 0x8388) },
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, if_usb_table);
-
-static void if_usb_receive(struct urb *urb);
-static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct if_usb_card *cardp);
-static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
- uint8_t *payload, uint16_t nb);
-static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
- uint16_t nb);
-static void if_usb_free(struct if_usb_card *cardp);
-static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
-static int if_usb_reset_device(struct if_usb_card *cardp);
-
-/**
- * @brief call back function to handle the status of the URB
- * @param urb pointer to urb structure
- * @return N/A
- */
-static void if_usb_write_bulk_callback(struct urb *urb)
-{
- struct if_usb_card *cardp = (struct if_usb_card *) urb->context;
-
- /* handle the transmission complete validations */
-
- if (urb->status == 0) {
- struct lbs_private *priv = cardp->priv;
-
- lbs_deb_usb2(&urb->dev->dev, "URB status is successful\n");
- lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
- urb->actual_length);
-
- /* Used for both firmware TX and regular TX. priv isn't
- * valid at firmware load time.
- */
- if (priv)
- lbs_host_to_card_done(priv);
- } else {
- /* print the failure status number for debug */
- lbs_pr_info("URB in failure status: %d\n", urb->status);
- }
-
- return;
-}
-
-/**
- * @brief free tx/rx urb, skb and rx buffer
- * @param cardp pointer if_usb_card
- * @return N/A
- */
-static void if_usb_free(struct if_usb_card *cardp)
-{
- lbs_deb_enter(LBS_DEB_USB);
-
- /* Unlink tx & rx urb */
- usb_kill_urb(cardp->tx_urb);
- usb_kill_urb(cardp->rx_urb);
-
- usb_free_urb(cardp->tx_urb);
- cardp->tx_urb = NULL;
-
- usb_free_urb(cardp->rx_urb);
- cardp->rx_urb = NULL;
-
- kfree(cardp->ep_out_buf);
- cardp->ep_out_buf = NULL;
-
- lbs_deb_leave(LBS_DEB_USB);
-}
-
-static void if_usb_setup_firmware(struct lbs_private *priv)
-{
- struct if_usb_card *cardp = priv->card;
- struct cmd_ds_set_boot2_ver b2_cmd;
- struct cmd_ds_802_11_fw_wake_method wake_method;
-
- b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
- b2_cmd.action = 0;
- b2_cmd.version = cardp->boot2_version;
-
- if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
- lbs_deb_usb("Setting boot2 version failed\n");
-
- priv->wol_gpio = 2; /* Wake via GPIO2... */
- priv->wol_gap = 20; /* ... after 20ms */
- lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA);
-
- wake_method.hdr.size = cpu_to_le16(sizeof(wake_method));
- wake_method.action = cpu_to_le16(CMD_ACT_GET);
- if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) {
- lbs_pr_info("Firmware does not seem to support PS mode\n");
- } else {
- if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) {
- lbs_deb_usb("Firmware seems to support PS with wake-via-command\n");
- priv->ps_supported = 1;
- } else {
- /* The versions which boot up this way don't seem to
- work even if we set it to the command interrupt */
- lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n");
- }
- }
-}
-
-static void if_usb_fw_timeo(unsigned long priv)
-{
- struct if_usb_card *cardp = (void *)priv;
-
- if (cardp->fwdnldover) {
- lbs_deb_usb("Download complete, no event. Assuming success\n");
- } else {
- lbs_pr_err("Download timed out\n");
- cardp->surprise_removed = 1;
- }
- wake_up(&cardp->fw_wq);
-}
-
-/**
- * @brief sets the configuration values
- * @param ifnum interface number
- * @param id pointer to usb_device_id
- * @return 0 on success, error code on failure
- */
-static int if_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev;
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
- struct lbs_private *priv;
- struct if_usb_card *cardp;
- int i;
-
- udev = interface_to_usbdev(intf);
-
- cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
- if (!cardp) {
- lbs_pr_err("Out of memory allocating private data.\n");
- goto error;
- }
-
- setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
- init_waitqueue_head(&cardp->fw_wq);
-
- cardp->udev = udev;
- iface_desc = intf->cur_altsetting;
-
- lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
- " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
- le16_to_cpu(udev->descriptor.bcdUSB),
- udev->descriptor.bDeviceClass,
- udev->descriptor.bDeviceSubClass,
- udev->descriptor.bDeviceProtocol);
-
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
- if (usb_endpoint_is_bulk_in(endpoint)) {
- cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize);
- cardp->ep_in = usb_endpoint_num(endpoint);
-
- lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
- lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
-
- } else if (usb_endpoint_is_bulk_out(endpoint)) {
- cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize);
- cardp->ep_out = usb_endpoint_num(endpoint);
-
- lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
- lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size);
- }
- }
- if (!cardp->ep_out_size || !cardp->ep_in_size) {
- lbs_deb_usbd(&udev->dev, "Endpoints not found\n");
- goto dealloc;
- }
- if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
- lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
- goto dealloc;
- }
- if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
- lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
- goto dealloc;
- }
- cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL);
- if (!cardp->ep_out_buf) {
- lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n");
- goto dealloc;
- }
-
- /* Upload firmware */
- if (if_usb_prog_firmware(cardp)) {
- lbs_deb_usbd(&udev->dev, "FW upload failed\n");
- goto err_prog_firmware;
- }
-
- if (!(priv = lbs_add_card(cardp, &udev->dev)))
- goto err_prog_firmware;
-
- cardp->priv = priv;
- cardp->priv->fw_ready = 1;
-
- priv->hw_host_to_card = if_usb_host_to_card;
- cardp->boot2_version = udev->descriptor.bcdDevice;
-
- if_usb_submit_rx_urb(cardp);
-
- if (lbs_start_card(priv))
- goto err_start_card;
-
- if_usb_setup_firmware(priv);
-
- usb_get_dev(udev);
- usb_set_intfdata(intf, cardp);
-
- return 0;
-
-err_start_card:
- lbs_remove_card(priv);
-err_prog_firmware:
- if_usb_reset_device(cardp);
-dealloc:
- if_usb_free(cardp);
-
-error:
- return -ENOMEM;
-}
-
-/**
- * @brief free resource and cleanup
- * @param intf USB interface structure
- * @return N/A
- */
-static void if_usb_disconnect(struct usb_interface *intf)
-{
- struct if_usb_card *cardp = usb_get_intfdata(intf);
- struct lbs_private *priv = (struct lbs_private *) cardp->priv;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- cardp->surprise_removed = 1;
-
- if (priv) {
- priv->surpriseremoved = 1;
- lbs_stop_card(priv);
- lbs_remove_card(priv);
- }
-
- /* Unlink and free urb */
- if_usb_free(cardp);
-
- usb_set_intfdata(intf, NULL);
- usb_put_dev(interface_to_usbdev(intf));
-
- lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-/**
- * @brief This function download FW
- * @param priv pointer to struct lbs_private
- * @return 0
- */
-static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
-{
- struct fwdata *fwdata = cardp->ep_out_buf;
- uint8_t *firmware = cardp->fw->data;
-
- /* If we got a CRC failure on the last block, back
- up and retry it */
- if (!cardp->CRC_OK) {
- cardp->totalbytes = cardp->fwlastblksent;
- cardp->fwseqnum--;
- }
-
- lbs_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
- cardp->totalbytes);
-
- /* struct fwdata (which we sent to the card) has an
- extra __le32 field in between the header and the data,
- which is not in the struct fwheader in the actual
- firmware binary. Insert the seqnum in the middle... */
- memcpy(&fwdata->hdr, &firmware[cardp->totalbytes],
- sizeof(struct fwheader));
-
- cardp->fwlastblksent = cardp->totalbytes;
- cardp->totalbytes += sizeof(struct fwheader);
-
- memcpy(fwdata->data, &firmware[cardp->totalbytes],
- le32_to_cpu(fwdata->hdr.datalength));
-
- lbs_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
- le32_to_cpu(fwdata->hdr.datalength));
-
- fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
- cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
-
- usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
- le32_to_cpu(fwdata->hdr.datalength));
-
- if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
- lbs_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
- lbs_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
- cardp->fwseqnum, cardp->totalbytes);
- } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
- lbs_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
- lbs_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
-
- cardp->fwfinalblk = 1;
- }
-
- lbs_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
- cardp->totalbytes);
-
- return 0;
-}
-
-static int if_usb_reset_device(struct if_usb_card *cardp)
-{
- struct cmd_ds_command *cmd = cardp->ep_out_buf + 4;
- int ret;
-
- lbs_deb_enter(LBS_DEB_USB);
-
- *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
-
- cmd->command = cpu_to_le16(CMD_802_11_RESET);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
- cmd->result = cpu_to_le16(0);
- cmd->seqnum = cpu_to_le16(0x5a5a);
- cmd->params.reset.action = cpu_to_le16(CMD_ACT_HALT);
- usb_tx_block(cardp, cardp->ep_out_buf, 4 + S_DS_GEN + sizeof(struct cmd_ds_802_11_reset));
-
- msleep(100);
- ret = usb_reset_device(cardp->udev);
- msleep(100);
-
-#ifdef CONFIG_OLPC
- if (ret && machine_is_olpc()) {
- printk(KERN_CRIT "Resetting OLPC wireless via EC...\n");
- olpc_ec_cmd(0x25, NULL, 0, NULL, 0);
- }
-#endif
-
- lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
-
- return ret;
-}
-
-/**
- * @brief This function transfer the data to the device.
- * @param priv pointer to struct lbs_private
- * @param payload pointer to payload data
- * @param nb data length
- * @return 0 or -1
- */
-static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb)
-{
- int ret = -1;
-
- /* check if device is removed */
- if (cardp->surprise_removed) {
- lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
- goto tx_ret;
- }
-
- usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
- usb_sndbulkpipe(cardp->udev,
- cardp->ep_out),
- payload, nb, if_usb_write_bulk_callback, cardp);
-
- cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
-
- if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
- lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
- ret = -1;
- } else {
- lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
- ret = 0;
- }
-
-tx_ret:
- return ret;
-}
-
-static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
- void (*callbackfn)(struct urb *urb))
-{
- struct sk_buff *skb;
- int ret = -1;
-
- if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
- lbs_pr_err("No free skb\n");
- goto rx_ret;
- }
-
- cardp->rx_skb = skb;
-
- /* Fill the receive configuration URB and initialise the Rx call back */
- usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
- usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
- (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),
- MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
- cardp);
-
- cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
-
- lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
- if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
- lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
- kfree_skb(skb);
- cardp->rx_skb = NULL;
- ret = -1;
- } else {
- lbs_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
- ret = 0;
- }
-
-rx_ret:
- return ret;
-}
-
-static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
-{
- return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
-}
-
-static int if_usb_submit_rx_urb(struct if_usb_card *cardp)
-{
- return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
-}
-
-static void if_usb_receive_fwload(struct urb *urb)
-{
- struct if_usb_card *cardp = urb->context;
- struct sk_buff *skb = cardp->rx_skb;
- struct fwsyncheader *syncfwheader;
- struct bootcmdresp bootcmdresp;
-
- if (urb->status) {
- lbs_deb_usbd(&cardp->udev->dev,
- "URB status is failed during fw load\n");
- kfree_skb(skb);
- return;
- }
-
- if (cardp->fwdnldover) {
- __le32 *tmp = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
-
- if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
- tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {
- lbs_pr_info("Firmware ready event received\n");
- wake_up(&cardp->fw_wq);
- } else {
- lbs_deb_usb("Waiting for confirmation; got %x %x\n",
- le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
- if_usb_submit_rx_urb_fwload(cardp);
- }
- kfree_skb(skb);
- return;
- }
- if (cardp->bootcmdresp <= 0) {
- memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
- sizeof(bootcmdresp));
-
- if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
- kfree_skb(skb);
- if_usb_submit_rx_urb_fwload(cardp);
- cardp->bootcmdresp = 1;
- lbs_deb_usbd(&cardp->udev->dev,
- "Received valid boot command response\n");
- return;
- }
- if (bootcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
- if (bootcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
- bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
- bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
- if (!cardp->bootcmdresp)
- lbs_pr_info("Firmware already seems alive; resetting\n");
- cardp->bootcmdresp = -1;
- } else {
- lbs_pr_info("boot cmd response wrong magic number (0x%x)\n",
- le32_to_cpu(bootcmdresp.magic));
- }
- } else if (bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
- lbs_pr_info("boot cmd response cmd_tag error (%d)\n",
- bootcmdresp.cmd);
- } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) {
- lbs_pr_info("boot cmd response result error (%d)\n",
- bootcmdresp.result);
- } else {
- cardp->bootcmdresp = 1;
- lbs_deb_usbd(&cardp->udev->dev,
- "Received valid boot command response\n");
- }
- kfree_skb(skb);
- if_usb_submit_rx_urb_fwload(cardp);
- return;
- }
-
- syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
- if (!syncfwheader) {
- lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
- kfree_skb(skb);
- return;
- }
-
- memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
- sizeof(struct fwsyncheader));
-
- if (!syncfwheader->cmd) {
- lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
- lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
- le32_to_cpu(syncfwheader->seqnum));
- cardp->CRC_OK = 1;
- } else {
- lbs_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
- cardp->CRC_OK = 0;
- }
-
- kfree_skb(skb);
-
- /* reschedule timer for 200ms hence */
- mod_timer(&cardp->fw_timeout, jiffies + (HZ/5));
-
- if (cardp->fwfinalblk) {
- cardp->fwdnldover = 1;
- goto exit;
- }
-
- if_usb_send_fw_pkt(cardp);
-
- exit:
- if_usb_submit_rx_urb_fwload(cardp);
-
- kfree(syncfwheader);
-
- return;
-}
-
-#define MRVDRV_MIN_PKT_LEN 30
-
-static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
- struct if_usb_card *cardp,
- struct lbs_private *priv)
-{
- if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
- || recvlength < MRVDRV_MIN_PKT_LEN) {
- lbs_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
- kfree_skb(skb);
- return;
- }
-
- skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
- skb_put(skb, recvlength);
- skb_pull(skb, MESSAGE_HEADER_LEN);
-
- lbs_process_rxed_packet(priv, skb);
-}
-
-static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
- struct sk_buff *skb,
- struct if_usb_card *cardp,
- struct lbs_private *priv)
-{
- u8 i;
-
- if (recvlength > LBS_CMD_BUFFER_SIZE) {
- lbs_deb_usbd(&cardp->udev->dev,
- "The receive buffer is too large\n");
- kfree_skb(skb);
- return;
- }
-
- if (!in_interrupt())
- BUG();
-
- spin_lock(&priv->driver_lock);
-
- i = (priv->resp_idx == 0) ? 1 : 0;
- BUG_ON(priv->resp_len[i]);
- priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN);
- memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN,
- priv->resp_len[i]);
- kfree_skb(skb);
- lbs_notify_command_response(priv, i);
-
- spin_unlock(&priv->driver_lock);
-
- lbs_deb_usbd(&cardp->udev->dev,
- "Wake up main thread to handle cmd response\n");
-}
-
-/**
- * @brief This function reads of the packet into the upload buff,
- * wake up the main thread and initialise the Rx callack.
- *
- * @param urb pointer to struct urb
- * @return N/A
- */
-static void if_usb_receive(struct urb *urb)
-{
- struct if_usb_card *cardp = urb->context;
- struct sk_buff *skb = cardp->rx_skb;
- struct lbs_private *priv = cardp->priv;
- int recvlength = urb->actual_length;
- uint8_t *recvbuff = NULL;
- uint32_t recvtype = 0;
- __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
- uint32_t event;
-
- lbs_deb_enter(LBS_DEB_USB);
-
- if (recvlength) {
- if (urb->status) {
- lbs_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
- urb->status);
- kfree_skb(skb);
- goto setup_for_next;
- }
-
- recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
- recvtype = le32_to_cpu(pkt[0]);
- lbs_deb_usbd(&cardp->udev->dev,
- "Recv length = 0x%x, Recv type = 0x%X\n",
- recvlength, recvtype);
- } else if (urb->status) {
- kfree_skb(skb);
- goto rx_exit;
- }
-
- switch (recvtype) {
- case CMD_TYPE_DATA:
- process_cmdtypedata(recvlength, skb, cardp, priv);
- break;
-
- case CMD_TYPE_REQUEST:
- process_cmdrequest(recvlength, recvbuff, skb, cardp, priv);
- break;
-
- case CMD_TYPE_INDICATION:
- /* Event handling */
- event = le32_to_cpu(pkt[1]);
- lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event);
- kfree_skb(skb);
-
- /* Icky undocumented magic special case */
- if (event & 0xffff0000) {
- u32 trycount = (event & 0xffff0000) >> 16;
-
- lbs_send_tx_feedback(priv, trycount);
- } else
- lbs_queue_event(priv, event & 0xFF);
- break;
-
- default:
- lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
- recvtype);
- kfree_skb(skb);
- break;
- }
-
-setup_for_next:
- if_usb_submit_rx_urb(cardp);
-rx_exit:
- lbs_deb_leave(LBS_DEB_USB);
-}
-
-/**
- * @brief This function downloads data to FW
- * @param priv pointer to struct lbs_private structure
- * @param type type of data
- * @param buf pointer to data buffer
- * @param len number of bytes
- * @return 0 or -1
- */
-static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
- uint8_t *payload, uint16_t nb)
-{
- struct if_usb_card *cardp = priv->card;
-
- lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type);
- lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb);
-
- if (type == MVMS_CMD) {
- *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
- priv->dnld_sent = DNLD_CMD_SENT;
- } else {
- *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA);
- priv->dnld_sent = DNLD_DATA_SENT;
- }
-
- memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb);
-
- return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN);
-}
-
-/**
- * @brief This function issues Boot command to the Boot2 code
- * @param ivalue 1:Boot from FW by USB-Download
- * 2:Boot from FW in EEPROM
- * @return 0
- */
-static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue)
-{
- struct bootcmd *bootcmd = cardp->ep_out_buf;
-
- /* Prepare command */
- bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
- bootcmd->cmd = ivalue;
- memset(bootcmd->pad, 0, sizeof(bootcmd->pad));
-
- /* Issue command */
- usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd));
-
- return 0;
-}
-
-
-/**
- * @brief This function checks the validity of Boot2/FW image.
- *
- * @param data pointer to image
- * len image length
- * @return 0 or -1
- */
-static int check_fwfile_format(uint8_t *data, uint32_t totlen)
-{
- uint32_t bincmd, exit;
- uint32_t blksize, offset, len;
- int ret;
-
- ret = 1;
- exit = len = 0;
-
- do {
- struct fwheader *fwh = (void *)data;
-
- bincmd = le32_to_cpu(fwh->dnldcmd);
- blksize = le32_to_cpu(fwh->datalength);
- switch (bincmd) {
- case FW_HAS_DATA_TO_RECV:
- offset = sizeof(struct fwheader) + blksize;
- data += offset;
- len += offset;
- if (len >= totlen)
- exit = 1;
- break;
- case FW_HAS_LAST_BLOCK:
- exit = 1;
- ret = 0;
- break;
- default:
- exit = 1;
- break;
- }
- } while (!exit);
-
- if (ret)
- lbs_pr_err("firmware file format check FAIL\n");
- else
- lbs_deb_fw("firmware file format check PASS\n");
-
- return ret;
-}
-
-
-static int if_usb_prog_firmware(struct if_usb_card *cardp)
-{
- int i = 0;
- static int reset_count = 10;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_USB);
-
- if ((ret = request_firmware(&cardp->fw, lbs_fw_name,
- &cardp->udev->dev)) < 0) {
- lbs_pr_err("request_firmware() failed with %#x\n", ret);
- lbs_pr_err("firmware %s not found\n", lbs_fw_name);
- goto done;
- }
-
- if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
- goto release_fw;
-
-restart:
- if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
- lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
- ret = -1;
- goto release_fw;
- }
-
- cardp->bootcmdresp = 0;
- do {
- int j = 0;
- i++;
- /* Issue Boot command = 1, Boot from Download-FW */
- if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
- /* wait for command response */
- do {
- j++;
- msleep_interruptible(100);
- } while (cardp->bootcmdresp == 0 && j < 10);
- } while (cardp->bootcmdresp == 0 && i < 5);
-
- if (cardp->bootcmdresp <= 0) {
- if (--reset_count >= 0) {
- if_usb_reset_device(cardp);
- goto restart;
- }
- return -1;
- }
-
- i = 0;
-
- cardp->totalbytes = 0;
- cardp->fwlastblksent = 0;
- cardp->CRC_OK = 1;
- cardp->fwdnldover = 0;
- cardp->fwseqnum = -1;
- cardp->totalbytes = 0;
- cardp->fwfinalblk = 0;
-
- /* Send the first firmware packet... */
- if_usb_send_fw_pkt(cardp);
-
- /* ... and wait for the process to complete */
- wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover);
-
- del_timer_sync(&cardp->fw_timeout);
- usb_kill_urb(cardp->rx_urb);
-
- if (!cardp->fwdnldover) {
- lbs_pr_info("failed to load fw, resetting device!\n");
- if (--reset_count >= 0) {
- if_usb_reset_device(cardp);
- goto restart;
- }
-
- lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
- ret = -1;
- goto release_fw;
- }
-
- release_fw:
- release_firmware(cardp->fw);
- cardp->fw = NULL;
-
- done:
- lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
- return ret;
-}
-
-
-#ifdef CONFIG_PM
-static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct if_usb_card *cardp = usb_get_intfdata(intf);
- struct lbs_private *priv = cardp->priv;
- int ret;
-
- lbs_deb_enter(LBS_DEB_USB);
-
- if (priv->psstate != PS_STATE_FULL_POWER)
- return -1;
-
- ret = lbs_suspend(priv);
- if (ret)
- goto out;
-
- /* Unlink tx & rx urb */
- usb_kill_urb(cardp->tx_urb);
- usb_kill_urb(cardp->rx_urb);
-
- out:
- lbs_deb_leave(LBS_DEB_USB);
- return ret;
-}
-
-static int if_usb_resume(struct usb_interface *intf)
-{
- struct if_usb_card *cardp = usb_get_intfdata(intf);
- struct lbs_private *priv = cardp->priv;
-
- lbs_deb_enter(LBS_DEB_USB);
-
- if_usb_submit_rx_urb(cardp);
-
- lbs_resume(priv);
-
- lbs_deb_leave(LBS_DEB_USB);
- return 0;
-}
-#else
-#define if_usb_suspend NULL
-#define if_usb_resume NULL
-#endif
-
-static struct usb_driver if_usb_driver = {
- .name = DRV_NAME,
- .probe = if_usb_probe,
- .disconnect = if_usb_disconnect,
- .id_table = if_usb_table,
- .suspend = if_usb_suspend,
- .resume = if_usb_resume,
- .reset_resume = if_usb_resume,
-};
-
-static int __init if_usb_init_module(void)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- ret = usb_register(&if_usb_driver);
-
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
- return ret;
-}
-
-static void __exit if_usb_exit_module(void)
-{
- lbs_deb_enter(LBS_DEB_MAIN);
-
- usb_deregister(&if_usb_driver);
-
- lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-module_init(if_usb_init_module);
-module_exit(if_usb_exit_module);
-
-MODULE_DESCRIPTION("8388 USB WLAN Driver");
-MODULE_AUTHOR("Marvell International Ltd. and Red Hat, Inc.");
-MODULE_LICENSE("GPL");
+++ /dev/null
-#ifndef _LBS_IF_USB_H
-#define _LBS_IF_USB_H
-
-#include <linux/wait.h>
-#include <linux/timer.h>
-
-struct lbs_private;
-
-/**
- * This file contains definition for USB interface.
- */
-#define CMD_TYPE_REQUEST 0xF00DFACE
-#define CMD_TYPE_DATA 0xBEADC0DE
-#define CMD_TYPE_INDICATION 0xBEEFFACE
-
-#define IPFIELD_ALIGN_OFFSET 2
-
-#define BOOT_CMD_FW_BY_USB 0x01
-#define BOOT_CMD_FW_IN_EEPROM 0x02
-#define BOOT_CMD_UPDATE_BOOT2 0x03
-#define BOOT_CMD_UPDATE_FW 0x04
-#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* LVRM */
-
-struct bootcmd
-{
- __le32 magic;
- uint8_t cmd;
- uint8_t pad[11];
-};
-
-#define BOOT_CMD_RESP_OK 0x0001
-#define BOOT_CMD_RESP_FAIL 0x0000
-
-struct bootcmdresp
-{
- __le32 magic;
- uint8_t cmd;
- uint8_t result;
- uint8_t pad[2];
-};
-
-/** USB card description structure*/
-struct if_usb_card {
- struct usb_device *udev;
- struct urb *rx_urb, *tx_urb;
- struct lbs_private *priv;
-
- struct sk_buff *rx_skb;
-
- uint8_t ep_in;
- uint8_t ep_out;
-
- int8_t bootcmdresp;
-
- int ep_in_size;
-
- void *ep_out_buf;
- int ep_out_size;
-
- const struct firmware *fw;
- struct timer_list fw_timeout;
- wait_queue_head_t fw_wq;
- uint32_t fwseqnum;
- uint32_t totalbytes;
- uint32_t fwlastblksent;
- uint8_t CRC_OK;
- uint8_t fwdnldover;
- uint8_t fwfinalblk;
- uint8_t surprise_removed;
-
- __le16 boot2_version;
-};
-
-/** fwheader */
-struct fwheader {
- __le32 dnldcmd;
- __le32 baseaddr;
- __le32 datalength;
- __le32 CRC;
-};
-
-#define FW_MAX_DATA_BLK_SIZE 600
-/** FWData */
-struct fwdata {
- struct fwheader hdr;
- __le32 seqnum;
- uint8_t data[0];
-};
-
-/** fwsyncheader */
-struct fwsyncheader {
- __le32 cmd;
- __le32 seqnum;
-};
-
-#define FW_HAS_DATA_TO_RECV 0x00000001
-#define FW_HAS_LAST_BLOCK 0x00000004
-
-
-#endif
+++ /dev/null
-/**
- * This file contains ioctl functions
- */
-
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-
-#include <net/iw_handler.h>
-#include <net/ieee80211.h>
-
-#include "host.h"
-#include "radiotap.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "wext.h"
-#include "cmd.h"
-#include "ioctl.h"
-
-#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN + \
- IW_ESSID_MAX_SIZE + \
- IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \
- IW_EV_QUAL_LEN + IW_ESSID_MAX_SIZE + \
- IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */
-
-#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
-
-static int lbs_set_region(struct lbs_private * priv, u16 region_code)
-{
- int i;
- int ret = 0;
-
- for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
- // use the region code to search for the index
- if (region_code == lbs_region_code_to_index[i]) {
- priv->regioncode = region_code;
- break;
- }
- }
-
- // if it's unidentified region code
- if (i >= MRVDRV_MAX_REGION_CODE) {
- lbs_deb_ioctl("region Code not identified\n");
- ret = -1;
- goto done;
- }
-
- if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
- ret = -EINVAL;
- }
-
-done:
- lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
- return ret;
-}
-
-static inline int hex2int(char c)
-{
- if (c >= '0' && c <= '9')
- return (c - '0');
- if (c >= 'a' && c <= 'f')
- return (c - 'a' + 10);
- if (c >= 'A' && c <= 'F')
- return (c - 'A' + 10);
- return -1;
-}
-
-/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
- into binary format (6 bytes).
-
- This function expects that each byte is represented with 2 characters
- (e.g., 11:2:11:11:11:11 is invalid)
-
- */
-static char *eth_str2addr(char *ethstr, u8 * addr)
-{
- int i, val, val2;
- char *pos = ethstr;
-
- /* get rid of initial blanks */
- while (*pos == ' ' || *pos == '\t')
- ++pos;
-
- for (i = 0; i < 6; i++) {
- val = hex2int(*pos++);
- if (val < 0)
- return NULL;
- val2 = hex2int(*pos++);
- if (val2 < 0)
- return NULL;
- addr[i] = (val * 16 + val2) & 0xff;
-
- if (i < 5 && *pos++ != ':')
- return NULL;
- }
- return pos;
-}
-
-/* this writes xx:xx:xx:xx:xx:xx into ethstr
- (ethstr must have space for 18 chars) */
-static int eth_addr2str(u8 * addr, char *ethstr)
-{
- int i;
- char *pos = ethstr;
-
- for (i = 0; i < 6; i++) {
- sprintf(pos, "%02x", addr[i] & 0xff);
- pos += 2;
- if (i < 5)
- *pos++ = ':';
- }
- return 17;
-}
-
-/**
- * @brief Add an entry to the BT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_bt_add_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char ethaddrs_str[18];
- char *pos;
- u8 ethaddr[ETH_ALEN];
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
- sizeof(ethaddrs_str)))
- return -EFAULT;
-
- if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
- lbs_pr_info("BT_ADD: Invalid MAC address\n");
- return -EINVAL;
- }
-
- lbs_deb_ioctl("BT: adding %s\n", ethaddrs_str);
- ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS,
- CMD_ACT_BT_ACCESS_ADD,
- CMD_OPTION_WAITFORRSP, 0, ethaddr);
- lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Delete an entry from the BT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_bt_del_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char ethaddrs_str[18];
- u8 ethaddr[ETH_ALEN];
- char *pos;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
- sizeof(ethaddrs_str)))
- return -EFAULT;
-
- if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
- lbs_pr_info("Invalid MAC address\n");
- return -EINVAL;
- }
-
- lbs_deb_ioctl("BT: deleting %s\n", ethaddrs_str);
-
- return (lbs_prepare_and_send_command(priv,
- CMD_BT_ACCESS,
- CMD_ACT_BT_ACCESS_DEL,
- CMD_OPTION_WAITFORRSP, 0, ethaddr));
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief Reset all entries from the BT table
- * @param priv A pointer to struct lbs_private structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_bt_reset_ioctl(struct lbs_private * priv)
-{
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- lbs_pr_alert( "BT: resetting\n");
-
- return (lbs_prepare_and_send_command(priv,
- CMD_BT_ACCESS,
- CMD_ACT_BT_ACCESS_RESET,
- CMD_OPTION_WAITFORRSP, 0, NULL));
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief List an entry from the BT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_bt_list_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- int pos;
- char *addr1;
- struct iwreq *wrq = (struct iwreq *)req;
- /* used to pass id and store the bt entry returned by the FW */
- union {
- u32 id;
- char addr1addr2[2 * ETH_ALEN];
- } param;
- static char outstr[64];
- char *pbuf = outstr;
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
- lbs_deb_ioctl("Copy from user failed\n");
- return -1;
- }
- param.id = simple_strtoul(outstr, NULL, 10);
- pos = sprintf(pbuf, "%d: ", param.id);
- pbuf += pos;
-
- ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS,
- CMD_ACT_BT_ACCESS_LIST,
- CMD_OPTION_WAITFORRSP, 0,
- (char *)¶m);
-
- if (ret == 0) {
- addr1 = param.addr1addr2;
-
- pos = sprintf(pbuf, "BT includes node ");
- pbuf += pos;
- pos = eth_addr2str(addr1, pbuf);
- pbuf += pos;
- } else {
- sprintf(pbuf, "(null)");
- pbuf += pos;
- }
-
- wrq->u.data.length = strlen(outstr);
- if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
- wrq->u.data.length)) {
- lbs_deb_ioctl("BT_LIST: Copy to user failed!\n");
- return -EFAULT;
- }
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0 ;
-}
-
-/**
- * @brief Sets inverted state of blacklist (non-zero if inverted)
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_bt_set_invert_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- int ret;
- struct iwreq *wrq = (struct iwreq *)req;
- union {
- u32 id;
- char addr1addr2[2 * ETH_ALEN];
- } param;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- param.id = SUBCMD_DATA(wrq) ;
- ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS,
- CMD_ACT_BT_ACCESS_SET_INVERT,
- CMD_OPTION_WAITFORRSP, 0,
- (char *)¶m);
- if (ret != 0)
- return -EFAULT;
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief Gets inverted state of blacklist (non-zero if inverted)
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_bt_get_invert_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- int ret;
- union {
- __le32 id;
- char addr1addr2[2 * ETH_ALEN];
- } param;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- ret = lbs_prepare_and_send_command(priv, CMD_BT_ACCESS,
- CMD_ACT_BT_ACCESS_GET_INVERT,
- CMD_OPTION_WAITFORRSP, 0,
- (char *)¶m);
-
- if (ret == 0)
- wrq->u.param.value = le32_to_cpu(param.id);
- else
- return -EFAULT;
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief Find the next parameter in an input string
- * @param ptr A pointer to the input parameter string
- * @return A pointer to the next parameter, or 0 if no parameters left.
- */
-static char * next_param(char * ptr)
-{
- if (!ptr) return NULL;
- while (*ptr == ' ' || *ptr == '\t') ++ptr;
- return (*ptr == '\0') ? NULL : ptr;
-}
-
-/**
- * @brief Add an entry to the FWT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_add_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[128];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr;
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
- lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
- return -EINVAL;
- }
-
- if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
- lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
- return -EINVAL;
- }
-
- if ((ptr = next_param(ptr)))
- fwt_access.metric =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.metric = cpu_to_le32(FWT_DEFAULT_METRIC);
-
- if ((ptr = next_param(ptr)))
- fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.dir = FWT_DEFAULT_DIR;
-
- if ((ptr = next_param(ptr)))
- fwt_access.rate = (u8) simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.rate = FWT_DEFAULT_RATE;
-
- if ((ptr = next_param(ptr)))
- fwt_access.ssn =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.ssn = cpu_to_le32(FWT_DEFAULT_SSN);
-
- if ((ptr = next_param(ptr)))
- fwt_access.dsn =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.dsn = cpu_to_le32(FWT_DEFAULT_DSN);
-
- if ((ptr = next_param(ptr)))
- fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
-
- if ((ptr = next_param(ptr)))
- fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.ttl = FWT_DEFAULT_TTL;
-
- if ((ptr = next_param(ptr)))
- fwt_access.expiration =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.expiration = cpu_to_le32(FWT_DEFAULT_EXPIRATION);
-
- if ((ptr = next_param(ptr)))
- fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
-
- if ((ptr = next_param(ptr)))
- fwt_access.snr =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.snr = cpu_to_le32(FWT_DEFAULT_SNR);
-
-#ifdef DEBUG
- {
- char ethaddr1_str[18], ethaddr2_str[18];
- eth_addr2str(fwt_access.da, ethaddr1_str);
- eth_addr2str(fwt_access.ra, ethaddr2_str);
- lbs_deb_ioctl("FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
- fwt_access.dir, ethaddr2_str);
- lbs_deb_ioctl("FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
- fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
- fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
- fwt_access.sleepmode, fwt_access.snr);
- }
-#endif
-
- ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_ADD,
- CMD_OPTION_WAITFORRSP, 0,
- (void *)&fwt_access);
-
- lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Delete an entry from the FWT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_del_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[64];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr;
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
- lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
- return -EINVAL;
- }
-
- if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
- lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
- return -EINVAL;
- }
-
- if ((ptr = next_param(ptr)))
- fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.dir = FWT_DEFAULT_DIR;
-
-#ifdef DEBUG
- {
- char ethaddr1_str[18], ethaddr2_str[18];
- lbs_deb_ioctl("FWT_DEL: line is %s\n", in_str);
- eth_addr2str(fwt_access.da, ethaddr1_str);
- eth_addr2str(fwt_access.ra, ethaddr2_str);
- lbs_deb_ioctl("FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
- ethaddr2_str, fwt_access.dir);
- }
-#endif
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_DEL,
- CMD_OPTION_WAITFORRSP, 0,
- (void *)&fwt_access);
- lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
- return ret;
-}
-
-
-/**
- * @brief Print route parameters
- * @param fwt_access struct cmd_ds_fwt_access with route info
- * @param buf destination buffer for route info
- */
-static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
-{
- buf += sprintf(buf, " ");
- buf += eth_addr2str(fwt_access.da, buf);
- buf += sprintf(buf, " ");
- buf += eth_addr2str(fwt_access.ra, buf);
- buf += sprintf(buf, " %u", fwt_access.valid);
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
- buf += sprintf(buf, " %u", fwt_access.dir);
- buf += sprintf(buf, " %u", fwt_access.rate);
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
- buf += sprintf(buf, " %u", fwt_access.hopcount);
- buf += sprintf(buf, " %u", fwt_access.ttl);
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
- buf += sprintf(buf, " %u", fwt_access.sleepmode);
- buf += sprintf(buf, " %u ", le32_to_cpu(fwt_access.snr));
- buf += eth_addr2str(fwt_access.prec, buf);
-}
-
-/**
- * @brief Lookup an entry in the FWT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_lookup_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[64];
- char *ptr;
- static struct cmd_ds_fwt_access fwt_access;
- static char out_str[128];
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
- lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
- return -EINVAL;
- }
-
-#ifdef DEBUG
- {
- char ethaddr1_str[18];
- lbs_deb_ioctl("FWT_LOOKUP: line is %s\n", in_str);
- eth_addr2str(fwt_access.da, ethaddr1_str);
- lbs_deb_ioctl("FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
- }
-#endif
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_LOOKUP,
- CMD_OPTION_WAITFORRSP, 0,
- (void *)&fwt_access);
-
- if (ret == 0)
- print_route(fwt_access, out_str);
- else
- sprintf(out_str, "(null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_deb_ioctl("FWT_LOOKUP: Copy to user failed!\n");
- return -EFAULT;
- }
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief Reset all entries from the FWT table
- * @param priv A pointer to struct lbs_private structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_reset_ioctl(struct lbs_private * priv)
-{
- lbs_deb_ioctl("FWT: resetting\n");
-
- return (lbs_prepare_and_send_command(priv,
- CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_RESET,
- CMD_OPTION_WAITFORRSP, 0, NULL));
-}
-
-/**
- * @brief List an entry from the FWT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_list_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[8];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr = in_str;
- static char out_str[128];
- char *pbuf = out_str;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) {
- ret = -EFAULT;
- goto out;
- }
-
- fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
- {
- lbs_deb_ioctl("FWT_LIST: line is %s\n", in_str);
- lbs_deb_ioctl("FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
- }
-#endif
-
- ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_LIST,
- CMD_OPTION_WAITFORRSP, 0, (void *)&fwt_access);
-
- if (ret == 0)
- print_route(fwt_access, pbuf);
- else
- pbuf += sprintf(pbuf, " (null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_deb_ioctl("FWT_LIST: Copy to user failed!\n");
- ret = -EFAULT;
- goto out;
- }
-
- ret = 0;
-
-out:
- lbs_deb_leave(LBS_DEB_IOCTL);
- return ret;
-}
-
-/**
- * @brief List an entry from the FRT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_list_route_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[64];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr = in_str;
- static char out_str[128];
- char *pbuf = out_str;
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
- {
- lbs_deb_ioctl("FWT_LIST_ROUTE: line is %s\n", in_str);
- lbs_deb_ioctl("FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
- }
-#endif
-
- ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_LIST_ROUTE,
- CMD_OPTION_WAITFORRSP, 0, (void *)&fwt_access);
-
- if (ret == 0) {
- print_route(fwt_access, pbuf);
- } else
- pbuf += sprintf(pbuf, " (null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_deb_ioctl("FWT_LIST_ROUTE: Copy to user failed!\n");
- return -EFAULT;
- }
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief List an entry from the FNT table
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_list_neighbor_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[8];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr = in_str;
- static char out_str[128];
- char *pbuf = out_str;
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- memset(&fwt_access, 0, sizeof(fwt_access));
- fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
- {
- lbs_deb_ioctl("FWT_LIST_NEIGHBOR: line is %s\n", in_str);
- lbs_deb_ioctl("FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
- }
-#endif
-
- ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_LIST_NEIGHBOR,
- CMD_OPTION_WAITFORRSP, 0,
- (void *)&fwt_access);
-
- if (ret == 0) {
- pbuf += sprintf(pbuf, " ra ");
- pbuf += eth_addr2str(fwt_access.ra, pbuf);
- pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
- pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
- pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
- } else
- pbuf += sprintf(pbuf, " (null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_deb_ioctl("FWT_LIST_NEIGHBOR: Copy to user failed!\n");
- return -EFAULT;
- }
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief Cleans up the route (FRT) and neighbor (FNT) tables
- * (Garbage Collection)
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_cleanup_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- static struct cmd_ds_fwt_access fwt_access;
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- lbs_deb_ioctl("FWT: cleaning up\n");
-
- memset(&fwt_access, 0, sizeof(fwt_access));
-
- ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_CLEANUP,
- CMD_OPTION_WAITFORRSP, 0,
- (void *)&fwt_access);
-
- if (ret == 0)
- wrq->u.param.value = le32_to_cpu(fwt_access.references);
- else
- return -EFAULT;
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-/**
- * @brief Gets firmware internal time (debug purposes)
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_fwt_time_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- static struct cmd_ds_fwt_access fwt_access;
- int ret;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- lbs_deb_ioctl("FWT: getting time\n");
-
- memset(&fwt_access, 0, sizeof(fwt_access));
-
- ret = lbs_prepare_and_send_command(priv, CMD_FWT_ACCESS,
- CMD_ACT_FWT_ACCESS_TIME,
- CMD_OPTION_WAITFORRSP, 0,
- (void *)&fwt_access);
-
- if (ret == 0)
- wrq->u.param.value = le32_to_cpu(fwt_access.references);
- else
- return -EFAULT;
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return 0;
-}
-
-
-/**
- * @brief Manages all mesh related ioctls
- * @param priv A pointer to struct lbs_private structure
- * @param req A pointer to ifreq structure
- * @param cmd The command type
- * @param host_subcmd The device code for the subcommand
- * 0: sets a value in the firmware
- * 1: retrieves an int from the firmware
- * @return 0 --success, otherwise fail
- */
-static int lbs_mesh_ioctl(struct lbs_private * priv, struct iwreq * wrq,
- int cmd, int subcmd)
-{
- struct cmd_ds_mesh_access mesh_access;
- int parameter;
- char str[128];
- char *ptr = str;
- int ret, i;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- memset(&mesh_access, 0, sizeof(mesh_access));
-
- if (cmd == LBS_SETONEINT_GETNONE) {
- parameter = SUBCMD_DATA(wrq);
-
- /* Convert rate from Mbps -> firmware rate index */
- if (subcmd == CMD_ACT_MESH_SET_BCAST_RATE)
- parameter = lbs_data_rate_to_fw_index(parameter);
-
- if (parameter < 0)
- return -EINVAL;
- mesh_access.data[0] = cpu_to_le32(parameter);
- } else if (subcmd == CMD_ACT_MESH_SET_LINK_COSTS) {
- if (copy_from_user(str, wrq->u.data.pointer, sizeof(str)))
- return -EFAULT;
-
- for (i = 0; i < COSTS_LIST_SIZE; i++) {
- mesh_access.data[i] = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- if (!(ptr = next_param(ptr)) && i!= (COSTS_LIST_SIZE - 1))
- return -EINVAL;
- }
- }
-
- ret = lbs_mesh_access(priv, subcmd, &mesh_access);
-
- if (ret != 0)
- return ret;
-
- if (cmd == LBS_SETNONE_GETONEINT) {
- u32 data = le32_to_cpu(mesh_access.data[0]);
-
- if (subcmd == CMD_ACT_MESH_GET_BCAST_RATE)
- wrq->u.param.value = lbs_fw_index_to_data_rate(data);
- else
- wrq->u.param.value = data;
- } else if (subcmd == CMD_ACT_MESH_GET_LINK_COSTS) {
- for (i = 0; i < COSTS_LIST_SIZE; i++)
- ptr += sprintf (ptr, " %u", le32_to_cpu(mesh_access.data[i]));
- wrq->u.data.length = strlen(str);
-
- if (copy_to_user(wrq->u.data.pointer, (char *)str,
- wrq->u.data.length)) {
- lbs_deb_ioctl("MESH_IOCTL: Copy to user failed!\n");
- ret = -EFAULT;
- }
- }
-
- lbs_deb_leave(LBS_DEB_IOCTL);
- return ret;
-}
-
-/**
- * @brief Control Beacon transmissions
- * @param priv A pointer to struct lbs_private structure
- * @param wrq A pointer to iwreq structure
- * @return 0 --success, otherwise fail
- */
-static int lbs_bcn_ioctl(struct lbs_private * priv, struct iwreq *wrq)
-{
- int ret;
- int data[2];
-
- memset(data, 0, sizeof(data));
- if (!wrq->u.data.length) {
- lbs_deb_ioctl("Get Beacon control\n");
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_BEACON_CTRL,
- CMD_ACT_GET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
- data[0] = priv->beacon_enable;
- data[1] = priv->beacon_period;
- if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
- lbs_deb_ioctl("Copy to user failed\n");
- return -EFAULT;
- }
-#define GET_TWO_INT 2
- wrq->u.data.length = GET_TWO_INT;
- } else {
- lbs_deb_ioctl("Set beacon control\n");
- if (wrq->u.data.length > 2)
- return -EINVAL;
- if (copy_from_user (data, wrq->u.data.pointer,
- sizeof(int) * wrq->u.data.length)) {
- lbs_deb_ioctl("Copy from user failed\n");
- return -EFAULT;
- }
- priv->beacon_enable = data[0];
- if (wrq->u.data.length > 1) {
- if ((data[1] > MRVDRV_MAX_BEACON_INTERVAL)
- || (data[1] < MRVDRV_MIN_BEACON_INTERVAL))
- return -ENOTSUPP;
- priv->beacon_period= data[1];
- }
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_BEACON_CTRL,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
- }
- return ret;
-}
-
-static int lbs_led_gpio_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- int i, ret = 0;
- int data[16];
- struct cmd_ds_802_11_led_ctrl ctrl;
- struct mrvlietypes_ledgpio *gpio = (struct mrvlietypes_ledgpio *) ctrl.data;
- int len = wrq->u.data.length;
-
- if ((len > MAX_LEDS * 2) || (len % 2 != 0))
- return -ENOTSUPP;
-
- memset(&ctrl, 0, sizeof(ctrl));
- if (len == 0) {
- ctrl.action = cpu_to_le16(CMD_ACT_GET);
- } else {
- if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * len)) {
- lbs_deb_ioctl("Copy from user failed\n");
- ret = -EFAULT;
- goto out;
- }
-
- ctrl.action = cpu_to_le16(CMD_ACT_SET);
- ctrl.numled = cpu_to_le16(0);
- gpio->header.type = cpu_to_le16(TLV_TYPE_LED_GPIO);
- gpio->header.len = cpu_to_le16(len);
- for (i = 0; i < len; i += 2) {
- gpio->ledpin[i / 2].led = data[i];
- gpio->ledpin[i / 2].pin = data[i + 1];
- }
- }
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_LED_GPIO_CTRL,
- 0, CMD_OPTION_WAITFORRSP, 0, (void *)&ctrl);
- if (ret) {
- lbs_deb_ioctl("Error doing LED GPIO control: %d\n", ret);
- goto out;
- }
- len = le16_to_cpu(gpio->header.len);
- for (i = 0; i < len; i += 2) {
- data[i] = gpio->ledpin[i / 2].led;
- data[i + 1] = gpio->ledpin[i / 2].pin;
- }
-
- if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * len)) {
- lbs_deb_ioctl("Copy to user failed\n");
- ret = -EFAULT;
- goto out;
- }
-
- wrq->u.data.length = len;
-
-out:
- return ret;
-}
-
-
-static int lbs_led_bhv_ioctl(struct lbs_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- int i, ret = 0;
- int data[MAX_LEDS*4];
- int firmwarestate = 0;
- struct cmd_ds_802_11_led_ctrl ctrl;
- struct mrvlietypes_ledbhv *bhv = (struct mrvlietypes_ledbhv *) ctrl.data;
- int len = wrq->u.data.length;
-
- if ((len > MAX_LEDS * 4) ||(len == 0) )
- return -ENOTSUPP;
-
- memset(&ctrl, 0, sizeof(ctrl));
- if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * len)) {
- lbs_deb_ioctl("Copy from user failed\n");
- ret = -EFAULT;
- goto out;
- }
- if (len == 1) {
- ctrl.action = cpu_to_le16(CMD_ACT_GET);
- firmwarestate = data[0];
- } else {
-
- if (len % 4 != 0 )
- return -ENOTSUPP;
-
- bhv->header.type = cpu_to_le16(TLV_TYPE_LEDBEHAVIOR);
- bhv->header.len = cpu_to_le16(len);
- ctrl.action = cpu_to_le16(CMD_ACT_SET);
- ctrl.numled = cpu_to_le16(0);
- for (i = 0; i < len; i += 4) {
- bhv->ledbhv[i / 4].firmwarestate = data[i];
- bhv->ledbhv[i / 4].led = data[i + 1];
- bhv->ledbhv[i / 4].ledstate = data[i + 2];
- bhv->ledbhv[i / 4].ledarg = data[i + 3];
- }
- }
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_LED_GPIO_CTRL,
- 0, CMD_OPTION_WAITFORRSP, 0, (void *)&ctrl);
- if (ret) {
- lbs_deb_ioctl("Error doing LED GPIO control: %d\n", ret);
- goto out;
- }
-
- /* Get LED behavior IE, we have received gpio control as well when len
- is equal to 1. */
- if (len ==1 ) {
- bhv = (struct mrvlietypes_ledbhv *)
- ((unsigned char *)bhv->ledbhv + le16_to_cpu(bhv->header.len));
- i = 0;
- while ( i < (MAX_LEDS*4) &&
- (bhv->header.type != cpu_to_le16(MRVL_TERMINATE_TLV_ID)) ) {
- if (bhv->ledbhv[0].firmwarestate == firmwarestate) {
- data[i++] = bhv->ledbhv[0].firmwarestate;
- data[i++] = bhv->ledbhv[0].led;
- data[i++] = bhv->ledbhv[0].ledstate;
- data[i++] = bhv->ledbhv[0].ledarg;
- }
- bhv++;
- }
- len = i;
- } else {
- for (i = 0; i < le16_to_cpu(bhv->header.len); i += 4) {
- data[i] = bhv->ledbhv[i / 4].firmwarestate;
- data[i + 1] = bhv->ledbhv[i / 4].led;
- data[i + 2] = bhv->ledbhv[i / 4].ledstate;
- data[i + 3] = bhv->ledbhv[i / 4].ledarg;
- }
- len = le16_to_cpu(bhv->header.len);
- }
-
- if (copy_to_user(wrq->u.data.pointer, data,
- sizeof(int) * len)) {
- lbs_deb_ioctl("Copy to user failed\n");
- ret = -EFAULT;
- goto out;
- }
-
- wrq->u.data.length = len;
-
-out:
- return ret;
-}
-
-/**
- * @brief ioctl function - entry point
- *
- * @param dev A pointer to net_device structure
- * @param req A pointer to ifreq structure
- * @param cmd command
- * @return 0--success, otherwise fail
- */
-int lbs_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
- int *pdata;
- int ret = 0;
- struct lbs_private *priv = dev->priv;
- struct iwreq *wrq = (struct iwreq *)req;
-
- lbs_deb_enter(LBS_DEB_IOCTL);
-
- lbs_deb_ioctl("lbs_do_ioctl: ioctl cmd = 0x%x\n", cmd);
- switch (cmd) {
- case LBS_SETNONE_GETNONE:
- switch (wrq->u.data.flags) {
- case LBS_SUBCMD_BT_RESET:
- lbs_bt_reset_ioctl(priv);
- break;
- case LBS_SUBCMD_FWT_RESET:
- lbs_fwt_reset_ioctl(priv);
- break;
- }
- break;
-
- case LBS_SETONEINT_GETNONE:
- switch (wrq->u.mode) {
- case LBS_SUBCMD_SET_REGION:
- ret = lbs_set_region(priv, (u16) SUBCMD_DATA(wrq));
- break;
- case LBS_SUBCMD_MESH_SET_TTL:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_SET_TTL);
- break;
- case LBS_SUBCMD_MESH_SET_BCAST_RATE:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_SET_BCAST_RATE);
- break;
- case LBS_SUBCMD_MESH_SET_RREQ_DELAY:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_SET_RREQ_DELAY);
- break;
- case LBS_SUBCMD_MESH_SET_ROUTE_EXP:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_SET_ROUTE_EXP);
- break;
- case LBS_SUBCMD_BT_SET_INVERT:
- ret = lbs_bt_set_invert_ioctl(priv, req);
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- break;
-
- case LBS_SET128CHAR_GET128CHAR:
- switch ((int)wrq->u.data.flags) {
- case LBS_SUBCMD_BT_ADD:
- ret = lbs_bt_add_ioctl(priv, req);
- break;
- case LBS_SUBCMD_BT_DEL:
- ret = lbs_bt_del_ioctl(priv, req);
- break;
- case LBS_SUBCMD_BT_LIST:
- ret = lbs_bt_list_ioctl(priv, req);
- break;
- case LBS_SUBCMD_FWT_ADD:
- ret = lbs_fwt_add_ioctl(priv, req);
- break;
- case LBS_SUBCMD_FWT_DEL:
- ret = lbs_fwt_del_ioctl(priv, req);
- break;
- case LBS_SUBCMD_FWT_LOOKUP:
- ret = lbs_fwt_lookup_ioctl(priv, req);
- break;
- case LBS_SUBCMD_FWT_LIST_NEIGHBOR:
- ret = lbs_fwt_list_neighbor_ioctl(priv, req);
- break;
- case LBS_SUBCMD_FWT_LIST:
- ret = lbs_fwt_list_ioctl(priv, req);
- break;
- case LBS_SUBCMD_FWT_LIST_ROUTE:
- ret = lbs_fwt_list_route_ioctl(priv, req);
- break;
- case LBS_SUBCMD_MESH_SET_LINK_COSTS:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_SET_LINK_COSTS);
- break ;
- case LBS_SUBCMD_MESH_GET_LINK_COSTS:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_GET_LINK_COSTS);
- break;
- }
- break;
-
- case LBS_SETNONE_GETONEINT:
- switch (wrq->u.mode) {
- case LBS_SUBCMD_GET_REGION:
- pdata = (int *)wrq->u.name;
- *pdata = (int)priv->regioncode;
- break;
- case LBS_SUBCMD_FWT_CLEANUP:
- ret = lbs_fwt_cleanup_ioctl(priv, req);
- break;
- case LBS_SUBCMD_FWT_TIME:
- ret = lbs_fwt_time_ioctl(priv, req);
- break;
- case LBS_SUBCMD_MESH_GET_TTL:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_GET_TTL);
- break;
- case LBS_SUBCMD_MESH_GET_BCAST_RATE:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_GET_BCAST_RATE);
- break;
- case LBS_SUBCMD_MESH_GET_RREQ_DELAY:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_GET_RREQ_DELAY);
- break;
- case LBS_SUBCMD_MESH_GET_ROUTE_EXP:
- ret = lbs_mesh_ioctl(priv, wrq, cmd,
- CMD_ACT_MESH_GET_ROUTE_EXP);
- break;
- case LBS_SUBCMD_BT_GET_INVERT:
- ret = lbs_bt_get_invert_ioctl(priv, req);
- break;
- default:
- ret = -EOPNOTSUPP;
- }
- break;
-
- case LBS_SET_GET_SIXTEEN_INT:
- switch ((int)wrq->u.data.flags) {
- case LBS_LED_GPIO_CTRL:
- ret = lbs_led_gpio_ioctl(priv, req);
- break;
- case LBS_BCN_CTRL:
- ret = lbs_bcn_ioctl(priv,wrq);
- break;
- case LBS_LED_BEHAVIOR_CTRL:
- ret = lbs_led_bhv_ioctl(priv, req);
- break;
- }
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
-
- lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
- return ret;
-}
+++ /dev/null
-#define COSTS_LIST_SIZE 4
-
-/* iwpriv places the subcmd number in the first uint32_t;
- data buffer follows that */
-#define SUBCMD_OFFSET sizeof(uint32_t)
-#define SUBCMD_DATA(x) *((int *)(x->u.name + SUBCMD_OFFSET))
-
-/** Private ioctls and ioctls subcommands */
-#define LBS_SETNONE_GETNONE (SIOCIWFIRSTPRIV + 8)
-#define LBS_SUBCMD_BT_RESET 13
-#define LBS_SUBCMD_FWT_RESET 14
-
-#define LBS_SETNONE_GETONEINT (SIOCIWFIRSTPRIV + 15)
-#define LBS_SUBCMD_GET_REGION 1
-#define LBS_SUBCMD_FWT_CLEANUP 15
-#define LBS_SUBCMD_FWT_TIME 16
-#define LBS_SUBCMD_MESH_GET_TTL 17
-#define LBS_SUBCMD_BT_GET_INVERT 18
-#define LBS_SUBCMD_MESH_GET_BCAST_RATE 19
-#define LBS_SUBCMD_MESH_GET_RREQ_DELAY 20
-#define LBS_SUBCMD_MESH_GET_ROUTE_EXP 21
-
-#define LBS_SETONEINT_GETNONE (SIOCIWFIRSTPRIV + 24)
-#define LBS_SUBCMD_SET_REGION 8
-#define LBS_SUBCMD_MESH_SET_TTL 18
-#define LBS_SUBCMD_BT_SET_INVERT 19
-#define LBS_SUBCMD_MESH_SET_BCAST_RATE 20
-#define LBS_SUBCMD_MESH_SET_RREQ_DELAY 21
-#define LBS_SUBCMD_MESH_SET_ROUTE_EXP 22
-
-#define LBS_SET128CHAR_GET128CHAR (SIOCIWFIRSTPRIV + 25)
-#define LBS_SUBCMD_BT_ADD 18
-#define LBS_SUBCMD_BT_DEL 19
-#define LBS_SUBCMD_BT_LIST 20
-#define LBS_SUBCMD_FWT_ADD 21
-#define LBS_SUBCMD_FWT_DEL 22
-#define LBS_SUBCMD_FWT_LOOKUP 23
-#define LBS_SUBCMD_FWT_LIST_NEIGHBOR 24
-#define LBS_SUBCMD_FWT_LIST 25
-#define LBS_SUBCMD_FWT_LIST_ROUTE 26
-#define LBS_SUBCMD_MESH_SET_LINK_COSTS 27
-#define LBS_SUBCMD_MESH_GET_LINK_COSTS 28
-
-#define LBS_SET_GET_SIXTEEN_INT (SIOCIWFIRSTPRIV + 29)
-#define LBS_LED_GPIO_CTRL 5
-#define LBS_BCN_CTRL 6
-#define LBS_LED_BEHAVIOR_CTRL 7
-
-int lbs_do_ioctl(struct net_device *dev, struct ifreq *req, int i);
+++ /dev/null
-/**
- * Functions implementing wlan infrastructure and adhoc join routines,
- * IOCTL handlers as well as command preperation and response routines
- * for sending adhoc start, adhoc join, and association commands
- * to the firmware.
- */
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-
-#include <net/iw_handler.h>
-
-#include "host.h"
-#include "decl.h"
-#include "join.h"
-#include "dev.h"
-#include "assoc.h"
-
-/* The firmware needs certain bits masked out of the beacon-derviced capability
- * field when associating/joining to BSSs.
- */
-#define CAPINFO_MASK (~(0xda00))
-
-/**
- * @brief This function finds common rates between rate1 and card rates.
- *
- * It will fill common rates in rate1 as output if found.
- *
- * NOTE: Setting the MSB of the basic rates need to be taken
- * care, either before or after calling this function
- *
- * @param priv A pointer to struct lbs_private structure
- * @param rate1 the buffer which keeps input and output
- * @param rate1_size the size of rate1 buffer; new size of buffer on return
- *
- * @return 0 or -1
- */
-static int get_common_rates(struct lbs_private *priv,
- u8 *rates,
- u16 *rates_size)
-{
- u8 *card_rates = lbs_bg_rates;
- size_t num_card_rates = sizeof(lbs_bg_rates);
- int ret = 0, i, j;
- u8 tmp[30];
- size_t tmp_size = 0;
-
- /* For each rate in card_rates that exists in rate1, copy to tmp */
- for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
- for (j = 0; rates[j] && (j < *rates_size); j++) {
- if (rates[j] == card_rates[i])
- tmp[tmp_size++] = card_rates[i];
- }
- }
-
- lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
- lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
- lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
- lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
-
- if (!priv->auto_rate) {
- for (i = 0; i < tmp_size; i++) {
- if (tmp[i] == priv->cur_rate)
- goto done;
- }
- lbs_pr_alert("Previously set fixed data rate %#x isn't "
- "compatible with the network.\n", priv->cur_rate);
- ret = -1;
- goto done;
- }
- ret = 0;
-
-done:
- memset(rates, 0, *rates_size);
- *rates_size = min_t(int, tmp_size, *rates_size);
- memcpy(rates, tmp, *rates_size);
- return ret;
-}
-
-
-/**
- * @brief Sets the MSB on basic rates as the firmware requires
- *
- * Scan through an array and set the MSB for basic data rates.
- *
- * @param rates buffer of data rates
- * @param len size of buffer
- */
-static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- if (rates[i] == 0x02 || rates[i] == 0x04 ||
- rates[i] == 0x0b || rates[i] == 0x16)
- rates[i] |= 0x80;
- }
-}
-
-/**
- * @brief Unsets the MSB on basic rates
- *
- * Scan through an array and unset the MSB for basic data rates.
- *
- * @param rates buffer of data rates
- * @param len size of buffer
- */
-void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- rates[i] &= 0x7f;
-}
-
-
-/**
- * @brief Associate to a specific BSS discovered in a scan
- *
- * @param priv A pointer to struct lbs_private structure
- * @param pbssdesc Pointer to the BSS descriptor to associate with.
- *
- * @return 0-success, otherwise fail
- */
-int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req)
-{
- int ret;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
- 0, CMD_OPTION_WAITFORRSP,
- 0, assoc_req->bss.bssid);
-
- if (ret)
- goto done;
-
- /* set preamble to firmware */
- if ( (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- && (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- else
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-
- lbs_set_radio_control(priv);
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
-
-done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Start an Adhoc Network
- *
- * @param priv A pointer to struct lbs_private structure
- * @param adhocssid The ssid of the Adhoc Network
- * @return 0--success, -1--fail
- */
-int lbs_start_adhoc_network(struct lbs_private *priv,
- struct assoc_request *assoc_req)
-{
- int ret = 0;
-
- priv->adhoccreate = 1;
-
- if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
- lbs_deb_join("AdhocStart: Short preamble\n");
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- } else {
- lbs_deb_join("AdhocStart: Long preamble\n");
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
- }
-
- lbs_set_radio_control(priv);
-
- lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
- lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
-
- return ret;
-}
-
-/**
- * @brief Join an adhoc network found in a previous scan
- *
- * @param priv A pointer to struct lbs_private structure
- * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
- * to attempt to join
- *
- * @return 0--success, -1--fail
- */
-int lbs_join_adhoc_network(struct lbs_private *priv,
- struct assoc_request *assoc_req)
-{
- struct bss_descriptor * bss = &assoc_req->bss;
- int ret = 0;
-
- lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
- __func__,
- escape_essid(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len),
- priv->curbssparams.ssid_len);
- lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
- __func__, escape_essid(bss->ssid, bss->ssid_len),
- bss->ssid_len);
-
- /* check if the requested SSID is already joined */
- if ( priv->curbssparams.ssid_len
- && !lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
- bss->ssid, bss->ssid_len)
- && (priv->mode == IW_MODE_ADHOC)
- && (priv->connect_status == LBS_CONNECTED)) {
- union iwreq_data wrqu;
-
- lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
- "current, not attempting to re-join");
-
- /* Send the re-association event though, because the association
- * request really was successful, even if just a null-op.
- */
- memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
- ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
- goto out;
- }
-
- /* Use shortpreamble only when both creator and card supports
- short preamble */
- if ( !(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- || !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
- lbs_deb_join("AdhocJoin: Long preamble\n");
- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
- } else {
- lbs_deb_join("AdhocJoin: Short preamble\n");
- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
- }
-
- lbs_set_radio_control(priv);
-
- lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
- lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
-
- priv->adhoccreate = 0;
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
- 0, CMD_OPTION_WAITFORRSP,
- OID_802_11_SSID, assoc_req);
-
-out:
- return ret;
-}
-
-int lbs_stop_adhoc_network(struct lbs_private *priv)
-{
- return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-}
-
-/**
- * @brief Send Deauthentication Request
- *
- * @param priv A pointer to struct lbs_private structure
- * @return 0--success, -1--fail
- */
-int lbs_send_deauthentication(struct lbs_private *priv)
-{
- return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-}
-
-/**
- * @brief This function prepares command of authenticate.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param cmd A pointer to cmd_ds_command structure
- * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
- *
- * @return 0 or -1
- */
-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf)
-{
- struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
- int ret = -1;
- u8 *bssid = pdata_buf;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
- + S_DS_GEN);
-
- /* translate auth mode to 802.11 defined wire value */
- switch (priv->secinfo.auth_mode) {
- case IW_AUTH_ALG_OPEN_SYSTEM:
- pauthenticate->authtype = 0x00;
- break;
- case IW_AUTH_ALG_SHARED_KEY:
- pauthenticate->authtype = 0x01;
- break;
- case IW_AUTH_ALG_LEAP:
- pauthenticate->authtype = 0x80;
- break;
- default:
- lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
- priv->secinfo.auth_mode);
- goto out;
- }
-
- memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
-
- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
- print_mac(mac, bssid), pauthenticate->authtype);
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd)
-{
- struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
- S_DS_GEN);
-
- /* set AP MAC address */
- memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
-
- /* Reason code 3 = Station is leaving */
-#define REASON_CODE_STA_LEAVING 3
- dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
-
-int lbs_cmd_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
- int ret = 0;
- struct assoc_request * assoc_req = pdata_buf;
- struct bss_descriptor * bss = &assoc_req->bss;
- u8 *pos;
- u16 tmpcap, tmplen;
- struct mrvlietypes_ssidparamset *ssid;
- struct mrvlietypes_phyparamset *phy;
- struct mrvlietypes_ssparamset *ss;
- struct mrvlietypes_ratesparamset *rates;
- struct mrvlietypes_rsnparamset *rsn;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- pos = (u8 *) passo;
-
- if (!priv) {
- ret = -1;
- goto done;
- }
-
- cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
-
- memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
- pos += sizeof(passo->peerstaaddr);
-
- /* set the listen interval */
- passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
-
- pos += sizeof(passo->capability);
- pos += sizeof(passo->listeninterval);
- pos += sizeof(passo->bcnperiod);
- pos += sizeof(passo->dtimperiod);
-
- ssid = (struct mrvlietypes_ssidparamset *) pos;
- ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
- tmplen = bss->ssid_len;
- ssid->header.len = cpu_to_le16(tmplen);
- memcpy(ssid->ssid, bss->ssid, tmplen);
- pos += sizeof(ssid->header) + tmplen;
-
- phy = (struct mrvlietypes_phyparamset *) pos;
- phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
- tmplen = sizeof(phy->fh_ds.dsparamset);
- phy->header.len = cpu_to_le16(tmplen);
- memcpy(&phy->fh_ds.dsparamset,
- &bss->phyparamset.dsparamset.currentchan,
- tmplen);
- pos += sizeof(phy->header) + tmplen;
-
- ss = (struct mrvlietypes_ssparamset *) pos;
- ss->header.type = cpu_to_le16(TLV_TYPE_CF);
- tmplen = sizeof(ss->cf_ibss.cfparamset);
- ss->header.len = cpu_to_le16(tmplen);
- pos += sizeof(ss->header) + tmplen;
-
- rates = (struct mrvlietypes_ratesparamset *) pos;
- rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
- memcpy(&rates->rates, &bss->rates, MAX_RATES);
- tmplen = MAX_RATES;
- if (get_common_rates(priv, rates->rates, &tmplen)) {
- ret = -1;
- goto done;
- }
- pos += sizeof(rates->header) + tmplen;
- rates->header.len = cpu_to_le16(tmplen);
- lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
-
- /* Copy the infra. association rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(rates->rates, tmplen);
-
- if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
- rsn = (struct mrvlietypes_rsnparamset *) pos;
- /* WPA_IE or WPA2_IE */
- rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
- tmplen = (u16) assoc_req->wpa_ie[1];
- rsn->header.len = cpu_to_le16(tmplen);
- memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
- lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
- sizeof(rsn->header) + tmplen);
- pos += sizeof(rsn->header) + tmplen;
- }
-
- /* update curbssparams */
- priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
-
- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
-
- /* set the capability info */
- tmpcap = (bss->capability & CAPINFO_MASK);
- if (bss->mode == IW_MODE_INFRA)
- tmpcap |= WLAN_CAPABILITY_ESS;
- passo->capability = cpu_to_le16(tmpcap);
- lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
-
-done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
- int ret = 0;
- int cmdappendsize = 0;
- struct assoc_request * assoc_req = pdata_buf;
- u16 tmpcap = 0;
- size_t ratesize = 0;
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- if (!priv) {
- ret = -1;
- goto done;
- }
-
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
-
- /*
- * Fill in the parameters for 2 data structures:
- * 1. cmd_ds_802_11_ad_hoc_start command
- * 2. priv->scantable[i]
- *
- * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
- * probe delay, and cap info.
- *
- * Firmware will fill up beacon period, DTIM, Basic rates
- * and operational rates.
- */
-
- memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
- memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
-
- lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
- assoc_req->ssid_len);
-
- /* set the BSS type */
- adhs->bsstype = CMD_BSS_TYPE_IBSS;
- priv->mode = IW_MODE_ADHOC;
- if (priv->beacon_period == 0)
- priv->beacon_period = MRVDRV_BEACON_INTERVAL;
- adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
-
- /* set Physical param set */
-#define DS_PARA_IE_ID 3
-#define DS_PARA_IE_LEN 1
-
- adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
- adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
-
- WARN_ON(!assoc_req->channel);
-
- lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
- assoc_req->channel);
-
- adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
-
- /* set IBSS param set */
-#define IBSS_PARA_IE_ID 6
-#define IBSS_PARA_IE_LEN 2
-
- adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
- adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
- adhs->ssparamset.ibssparamset.atimwindow = 0;
-
- /* set capability info */
- tmpcap = WLAN_CAPABILITY_IBSS;
- if (assoc_req->secinfo.wep_enabled) {
- lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
- tmpcap |= WLAN_CAPABILITY_PRIVACY;
- } else {
- lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
- }
- adhs->capability = cpu_to_le16(tmpcap);
-
- /* probedelay */
- adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-
- memset(adhs->rates, 0, sizeof(adhs->rates));
- ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
- memcpy(adhs->rates, lbs_bg_rates, ratesize);
-
- /* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(adhs->rates, ratesize);
-
- lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
- adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
-
- lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
-
- if (lbs_create_dnld_countryinfo_11d(priv)) {
- lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
- S_DS_GEN + cmdappendsize);
-
- ret = 0;
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
- struct cmd_ds_command *cmd)
-{
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
- cmd->size = cpu_to_le16(S_DS_GEN);
-
- return 0;
-}
-
-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
-{
- struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
- struct assoc_request * assoc_req = pdata_buf;
- struct bss_descriptor *bss = &assoc_req->bss;
- int cmdappendsize = 0;
- int ret = 0;
- u16 ratesize = 0;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
-
- join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
- join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
-
- memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
- memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
-
- memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
- sizeof(union ieeetypes_phyparamset));
-
- memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
- sizeof(union IEEEtypes_ssparamset));
-
- join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
- lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
- bss->capability, CAPINFO_MASK);
-
- /* information on BSSID descriptor passed to FW */
- lbs_deb_join(
- "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
- print_mac(mac, join_cmd->bss.bssid),
- join_cmd->bss.ssid);
-
- /* failtimeout */
- join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
-
- /* probedelay */
- join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-
- priv->curbssparams.channel = bss->channel;
-
- /* Copy Data rates from the rates recorded in scan response */
- memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
- ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
- memcpy(join_cmd->bss.rates, bss->rates, ratesize);
- if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
- lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
- ret = -1;
- goto done;
- }
-
- /* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
- memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
-
- /* Set MSB on basic rates as the firmware requires, but _after_
- * copying to current bss rates.
- */
- lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
-
- join_cmd->bss.ssparamset.ibssparamset.atimwindow =
- cpu_to_le16(bss->atimwindow);
-
- if (assoc_req->secinfo.wep_enabled) {
- u16 tmp = le16_to_cpu(join_cmd->bss.capability);
- tmp |= WLAN_CAPABILITY_PRIVACY;
- join_cmd->bss.capability = cpu_to_le16(tmp);
- }
-
- if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
- /* wake up first */
- __le32 Localpsmode;
-
- Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_PS_MODE,
- CMD_ACT_SET,
- 0, 0, &Localpsmode);
-
- if (ret) {
- ret = -1;
- goto done;
- }
- }
-
- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
- ret = -1;
- goto done;
- }
-
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
- S_DS_GEN + cmdappendsize);
-
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_ret_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- int ret = 0;
- union iwreq_data wrqu;
- struct ieeetypes_assocrsp *passocrsp;
- struct bss_descriptor * bss;
- u16 status_code;
-
- lbs_deb_enter(LBS_DEB_ASSOC);
-
- if (!priv->in_progress_assoc_req) {
- lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
- ret = -1;
- goto done;
- }
- bss = &priv->in_progress_assoc_req->bss;
-
- passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
-
- /*
- * Older FW versions map the IEEE 802.11 Status Code in the association
- * response to the following values returned in passocrsp->statuscode:
- *
- * IEEE Status Code Marvell Status Code
- * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
- * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
- * others -> 0x0003 ASSOC_RESULT_REFUSED
- *
- * Other response codes:
- * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
- * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
- * association response from the AP)
- */
-
- status_code = le16_to_cpu(passocrsp->statuscode);
- switch (status_code) {
- case 0x00:
- break;
- case 0x01:
- lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
- break;
- case 0x02:
- lbs_deb_assoc("ASSOC_RESP: internal timer "
- "expired while waiting for the AP\n");
- break;
- case 0x03:
- lbs_deb_assoc("ASSOC_RESP: association "
- "refused by AP\n");
- break;
- case 0x04:
- lbs_deb_assoc("ASSOC_RESP: authentication "
- "refused by AP\n");
- break;
- default:
- lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
- " unknown\n", status_code);
- break;
- }
-
- if (status_code) {
- lbs_mac_event_disconnected(priv);
- ret = -1;
- goto done;
- }
-
- lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
- le16_to_cpu(resp->size) - S_DS_GEN);
-
- /* Send a Media Connected event, according to the Spec */
- priv->connect_status = LBS_CONNECTED;
-
- /* Update current SSID and BSSID */
- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
- priv->curbssparams.ssid_len = bss->ssid_len;
- memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
- lbs_deb_assoc("ASSOC_RESP: currentpacketfilter is 0x%x\n",
- priv->currentpacketfilter);
-
- priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
- priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
-
- memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
- memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
- priv->nextSNRNF = 0;
- priv->numSNRNF = 0;
-
- netif_carrier_on(priv->dev);
- if (!priv->tx_pending_len)
- netif_wake_queue(priv->dev);
-
- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
-done:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
- return ret;
-}
-
-int lbs_ret_80211_disassociate(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- lbs_deb_enter(LBS_DEB_JOIN);
-
- lbs_mac_event_disconnected(priv);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
-
-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- int ret = 0;
- u16 command = le16_to_cpu(resp->command);
- u16 result = le16_to_cpu(resp->result);
- struct cmd_ds_802_11_ad_hoc_result *padhocresult;
- union iwreq_data wrqu;
- struct bss_descriptor *bss;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_JOIN);
-
- padhocresult = &resp->params.result;
-
- lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
- lbs_deb_join("ADHOC_RESP: command = %x\n", command);
- lbs_deb_join("ADHOC_RESP: result = %x\n", result);
-
- if (!priv->in_progress_assoc_req) {
- lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
- ret = -1;
- goto done;
- }
- bss = &priv->in_progress_assoc_req->bss;
-
- /*
- * Join result code 0 --> SUCCESS
- */
- if (result) {
- lbs_deb_join("ADHOC_RESP: failed\n");
- if (priv->connect_status == LBS_CONNECTED) {
- lbs_mac_event_disconnected(priv);
- }
- ret = -1;
- goto done;
- }
-
- /*
- * Now the join cmd should be successful
- * If BSSID has changed use SSID to compare instead of BSSID
- */
- lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
- escape_essid(bss->ssid, bss->ssid_len));
-
- /* Send a Media Connected event, according to the Spec */
- priv->connect_status = LBS_CONNECTED;
-
- if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
- /* Update the created network descriptor with the new BSSID */
- memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
- }
-
- /* Set the BSSID from the joined/started descriptor */
- memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
- /* Set the new SSID to current SSID */
- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
- priv->curbssparams.ssid_len = bss->ssid_len;
-
- netif_carrier_on(priv->dev);
- if (!priv->tx_pending_len)
- netif_wake_queue(priv->dev);
-
- memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
- lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
- lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
- lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
- print_mac(mac, padhocresult->bssid));
-
-done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
- return ret;
-}
-
-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- lbs_deb_enter(LBS_DEB_JOIN);
-
- lbs_mac_event_disconnected(priv);
-
- lbs_deb_leave(LBS_DEB_JOIN);
- return 0;
-}
+++ /dev/null
-/**
- * Interface for the wlan infrastructure and adhoc join routines
- *
- * Driver interface functions and type declarations for the join module
- * implemented in join.c. Process all start/join requests for
- * both adhoc and infrastructure networks
- */
-#ifndef _LBS_JOIN_H
-#define _LBS_JOIN_H
-
-#include "defs.h"
-#include "dev.h"
-
-struct cmd_ds_command;
-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
- struct cmd_ds_command *cmd);
-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
- struct cmd_ds_command *cmd);
-int lbs_cmd_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- void *pdata_buf);
-
-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
- struct cmd_ds_command *resp);
-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
- struct cmd_ds_command *resp);
-int lbs_ret_80211_disassociate(struct lbs_private *priv,
- struct cmd_ds_command *resp);
-int lbs_ret_80211_associate(struct lbs_private *priv,
- struct cmd_ds_command *resp);
-
-int lbs_start_adhoc_network(struct lbs_private *priv,
- struct assoc_request * assoc_req);
-int lbs_join_adhoc_network(struct lbs_private *priv,
- struct assoc_request * assoc_req);
-int lbs_stop_adhoc_network(struct lbs_private *priv);
-
-int lbs_send_deauthentication(struct lbs_private *priv);
-
-int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req);
-
-void lbs_unset_basic_rate_flags(u8 *rates, size_t len);
-
-#endif
+++ /dev/null
-/**
- * This file contains the major functions in WLAN
- * driver. It includes init, exit, open, close and main
- * thread etc..
- */
-
-#include <linux/moduleparam.h>
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/kthread.h>
-#include <linux/kfifo.h>
-#ifdef CONFIG_OLPC
-#include <asm/olpc.h>
-#endif
-
-#include <net/iw_handler.h>
-#include <net/ieee80211.h>
-
-#include "host.h"
-#include "decl.h"
-#include "dev.h"
-#include "wext.h"
-#include "debugfs.h"
-#include "scan.h"
-#include "assoc.h"
-#include "cmd.h"
-#include "ioctl.h"
-
-#define DRIVER_RELEASE_VERSION "323.p0"
-const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
-#ifdef DEBUG
- "-dbg"
-#endif
- "";
-
-
-/* Module parameters */
-unsigned int lbs_debug;
-EXPORT_SYMBOL_GPL(lbs_debug);
-module_param_named(libertas_debug, lbs_debug, int, 0644);
-
-
-/* This global structure is used to send the confirm_sleep command as
- * fast as possible down to the firmware. */
-struct cmd_confirm_sleep confirm_sleep;
-
-
-#define LBS_TX_PWR_DEFAULT 20 /*100mW */
-#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
-#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
-#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
-#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
-
-/* Format { channel, frequency (MHz), maxtxpower } */
-/* band: 'B/G', region: USA FCC/Canada IC */
-static struct chan_freq_power channel_freq_power_US_BG[] = {
- {1, 2412, LBS_TX_PWR_US_DEFAULT},
- {2, 2417, LBS_TX_PWR_US_DEFAULT},
- {3, 2422, LBS_TX_PWR_US_DEFAULT},
- {4, 2427, LBS_TX_PWR_US_DEFAULT},
- {5, 2432, LBS_TX_PWR_US_DEFAULT},
- {6, 2437, LBS_TX_PWR_US_DEFAULT},
- {7, 2442, LBS_TX_PWR_US_DEFAULT},
- {8, 2447, LBS_TX_PWR_US_DEFAULT},
- {9, 2452, LBS_TX_PWR_US_DEFAULT},
- {10, 2457, LBS_TX_PWR_US_DEFAULT},
- {11, 2462, LBS_TX_PWR_US_DEFAULT}
-};
-
-/* band: 'B/G', region: Europe ETSI */
-static struct chan_freq_power channel_freq_power_EU_BG[] = {
- {1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
- {2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
- {3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
- {4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
- {5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
- {6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
- {7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
- {8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
- {9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
- {10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
- {11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
- {12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
- {13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
-};
-
-/* band: 'B/G', region: Spain */
-static struct chan_freq_power channel_freq_power_SPN_BG[] = {
- {10, 2457, LBS_TX_PWR_DEFAULT},
- {11, 2462, LBS_TX_PWR_DEFAULT}
-};
-
-/* band: 'B/G', region: France */
-static struct chan_freq_power channel_freq_power_FR_BG[] = {
- {10, 2457, LBS_TX_PWR_FR_DEFAULT},
- {11, 2462, LBS_TX_PWR_FR_DEFAULT},
- {12, 2467, LBS_TX_PWR_FR_DEFAULT},
- {13, 2472, LBS_TX_PWR_FR_DEFAULT}
-};
-
-/* band: 'B/G', region: Japan */
-static struct chan_freq_power channel_freq_power_JPN_BG[] = {
- {1, 2412, LBS_TX_PWR_JP_DEFAULT},
- {2, 2417, LBS_TX_PWR_JP_DEFAULT},
- {3, 2422, LBS_TX_PWR_JP_DEFAULT},
- {4, 2427, LBS_TX_PWR_JP_DEFAULT},
- {5, 2432, LBS_TX_PWR_JP_DEFAULT},
- {6, 2437, LBS_TX_PWR_JP_DEFAULT},
- {7, 2442, LBS_TX_PWR_JP_DEFAULT},
- {8, 2447, LBS_TX_PWR_JP_DEFAULT},
- {9, 2452, LBS_TX_PWR_JP_DEFAULT},
- {10, 2457, LBS_TX_PWR_JP_DEFAULT},
- {11, 2462, LBS_TX_PWR_JP_DEFAULT},
- {12, 2467, LBS_TX_PWR_JP_DEFAULT},
- {13, 2472, LBS_TX_PWR_JP_DEFAULT},
- {14, 2484, LBS_TX_PWR_JP_DEFAULT}
-};
-
-/**
- * the structure for channel, frequency and power
- */
-struct region_cfp_table {
- u8 region;
- struct chan_freq_power *cfp_BG;
- int cfp_no_BG;
-};
-
-/**
- * the structure for the mapping between region and CFP
- */
-static struct region_cfp_table region_cfp_table[] = {
- {0x10, /*US FCC */
- channel_freq_power_US_BG,
- ARRAY_SIZE(channel_freq_power_US_BG),
- }
- ,
- {0x20, /*CANADA IC */
- channel_freq_power_US_BG,
- ARRAY_SIZE(channel_freq_power_US_BG),
- }
- ,
- {0x30, /*EU*/ channel_freq_power_EU_BG,
- ARRAY_SIZE(channel_freq_power_EU_BG),
- }
- ,
- {0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
- ARRAY_SIZE(channel_freq_power_SPN_BG),
- }
- ,
- {0x32, /*FRANCE*/ channel_freq_power_FR_BG,
- ARRAY_SIZE(channel_freq_power_FR_BG),
- }
- ,
- {0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
- ARRAY_SIZE(channel_freq_power_JPN_BG),
- }
- ,
-/*Add new region here */
-};
-
-/**
- * the table to keep region code
- */
-u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
- { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
-
-/**
- * 802.11b/g supported bitrates (in 500Kb/s units)
- */
-u8 lbs_bg_rates[MAX_RATES] =
- { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
-0x00, 0x00 };
-
-/**
- * FW rate table. FW refers to rates by their index in this table, not by the
- * rate value itself. Values of 0x00 are
- * reserved positions.
- */
-static u8 fw_data_rates[MAX_RATES] =
- { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
- 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
-};
-
-/**
- * @brief use index to get the data rate
- *
- * @param idx The index of data rate
- * @return data rate or 0
- */
-u32 lbs_fw_index_to_data_rate(u8 idx)
-{
- if (idx >= sizeof(fw_data_rates))
- idx = 0;
- return fw_data_rates[idx];
-}
-
-/**
- * @brief use rate to get the index
- *
- * @param rate data rate
- * @return index or 0
- */
-u8 lbs_data_rate_to_fw_index(u32 rate)
-{
- u8 i;
-
- if (!rate)
- return 0;
-
- for (i = 0; i < sizeof(fw_data_rates); i++) {
- if (rate == fw_data_rates[i])
- return i;
- }
- return 0;
-}
-
-/**
- * Attributes exported through sysfs
- */
-
-/**
- * @brief Get function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_get(struct device *dev,
- struct device_attribute *attr, char * buf)
-{
- struct lbs_private *priv = to_net_dev(dev)->priv;
- struct cmd_ds_mesh_access mesh_access;
- int ret;
-
- memset(&mesh_access, 0, sizeof(mesh_access));
-
- ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
- if (ret)
- return ret;
-
- return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
-}
-
-/**
- * @brief Set function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_set(struct device *dev,
- struct device_attribute *attr, const char * buf, size_t count)
-{
- struct lbs_private *priv = to_net_dev(dev)->priv;
- struct cmd_ds_mesh_access mesh_access;
- uint32_t datum;
- int ret;
-
- memset(&mesh_access, 0, sizeof(mesh_access));
- sscanf(buf, "%x", &datum);
- mesh_access.data[0] = cpu_to_le32(datum);
-
- ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
- if (ret)
- return ret;
-
- return strlen(buf);
-}
-
-static int lbs_add_rtap(struct lbs_private *priv);
-static void lbs_remove_rtap(struct lbs_private *priv);
-static int lbs_add_mesh(struct lbs_private *priv);
-static void lbs_remove_mesh(struct lbs_private *priv);
-
-
-/**
- * Get function for sysfs attribute rtap
- */
-static ssize_t lbs_rtap_get(struct device *dev,
- struct device_attribute *attr, char * buf)
-{
- struct lbs_private *priv = to_net_dev(dev)->priv;
- return snprintf(buf, 5, "0x%X\n", priv->monitormode);
-}
-
-/**
- * Set function for sysfs attribute rtap
- */
-static ssize_t lbs_rtap_set(struct device *dev,
- struct device_attribute *attr, const char * buf, size_t count)
-{
- int monitor_mode;
- struct lbs_private *priv = to_net_dev(dev)->priv;
-
- sscanf(buf, "%x", &monitor_mode);
- if (monitor_mode) {
- if (priv->monitormode == monitor_mode)
- return strlen(buf);
- if (!priv->monitormode) {
- if (priv->infra_open || priv->mesh_open)
- return -EBUSY;
- if (priv->mode == IW_MODE_INFRA)
- lbs_send_deauthentication(priv);
- else if (priv->mode == IW_MODE_ADHOC)
- lbs_stop_adhoc_network(priv);
- lbs_add_rtap(priv);
- }
- priv->monitormode = monitor_mode;
- }
-
- else {
- if (!priv->monitormode)
- return strlen(buf);
- priv->monitormode = 0;
- lbs_remove_rtap(priv);
-
- if (priv->currenttxskb) {
- dev_kfree_skb_any(priv->currenttxskb);
- priv->currenttxskb = NULL;
- }
-
- /* Wake queues, command thread, etc. */
- lbs_host_to_card_done(priv);
- }
-
- lbs_prepare_and_send_command(priv,
- CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
- return strlen(buf);
-}
-
-/**
- * lbs_rtap attribute to be exported per ethX interface
- * through sysfs (/sys/class/net/ethX/lbs_rtap)
- */
-static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
-
-/**
- * Get function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_get(struct device *dev,
- struct device_attribute *attr, char * buf)
-{
- struct lbs_private *priv = to_net_dev(dev)->priv;
- return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
-}
-
-/**
- * Set function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_set(struct device *dev,
- struct device_attribute *attr, const char * buf, size_t count)
-{
- struct lbs_private *priv = to_net_dev(dev)->priv;
- int enable;
- int ret;
-
- sscanf(buf, "%x", &enable);
- enable = !!enable;
- if (enable == !!priv->mesh_dev)
- return count;
-
- ret = lbs_mesh_config(priv, enable, priv->curbssparams.channel);
- if (ret)
- return ret;
-
- if (enable)
- lbs_add_mesh(priv);
- else
- lbs_remove_mesh(priv);
-
- return count;
-}
-
-/**
- * lbs_mesh attribute to be exported per ethX interface
- * through sysfs (/sys/class/net/ethX/lbs_mesh)
- */
-static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
-
-/**
- * anycast_mask attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/anycast_mask)
- */
-static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
-
-static struct attribute *lbs_mesh_sysfs_entries[] = {
- &dev_attr_anycast_mask.attr,
- NULL,
-};
-
-static struct attribute_group lbs_mesh_attr_group = {
- .attrs = lbs_mesh_sysfs_entries,
-};
-
-/**
- * @brief This function opens the ethX or mshX interface
- *
- * @param dev A pointer to net_device structure
- * @return 0 or -EBUSY if monitor mode active
- */
-static int lbs_dev_open(struct net_device *dev)
-{
- struct lbs_private *priv = (struct lbs_private *) dev->priv ;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_NET);
-
- spin_lock_irq(&priv->driver_lock);
-
- if (priv->monitormode) {
- ret = -EBUSY;
- goto out;
- }
-
- if (dev == priv->mesh_dev) {
- priv->mesh_open = 1;
- priv->mesh_connect_status = LBS_CONNECTED;
- netif_carrier_on(dev);
- } else {
- priv->infra_open = 1;
-
- if (priv->connect_status == LBS_CONNECTED)
- netif_carrier_on(dev);
- else
- netif_carrier_off(dev);
- }
-
- if (!priv->tx_pending_len)
- netif_wake_queue(dev);
- out:
-
- spin_unlock_irq(&priv->driver_lock);
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function closes the mshX interface
- *
- * @param dev A pointer to net_device structure
- * @return 0
- */
-static int lbs_mesh_stop(struct net_device *dev)
-{
- struct lbs_private *priv = (struct lbs_private *) (dev->priv);
-
- lbs_deb_enter(LBS_DEB_MESH);
- spin_lock_irq(&priv->driver_lock);
-
- priv->mesh_open = 0;
- priv->mesh_connect_status = LBS_DISCONNECTED;
-
- netif_stop_queue(dev);
- netif_carrier_off(dev);
-
- spin_unlock_irq(&priv->driver_lock);
-
- lbs_deb_leave(LBS_DEB_MESH);
- return 0;
-}
-
-/**
- * @brief This function closes the ethX interface
- *
- * @param dev A pointer to net_device structure
- * @return 0
- */
-static int lbs_eth_stop(struct net_device *dev)
-{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
-
- lbs_deb_enter(LBS_DEB_NET);
-
- spin_lock_irq(&priv->driver_lock);
- priv->infra_open = 0;
- netif_stop_queue(dev);
- spin_unlock_irq(&priv->driver_lock);
-
- lbs_deb_leave(LBS_DEB_NET);
- return 0;
-}
-
-static void lbs_tx_timeout(struct net_device *dev)
-{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
-
- lbs_deb_enter(LBS_DEB_TX);
-
- lbs_pr_err("tx watch dog timeout\n");
-
- dev->trans_start = jiffies;
-
- if (priv->currenttxskb)
- lbs_send_tx_feedback(priv, 0);
-
- /* XX: Shouldn't we also call into the hw-specific driver
- to kick it somehow? */
- lbs_host_to_card_done(priv);
-
- /* More often than not, this actually happens because the
- firmware has crapped itself -- rather than just a very
- busy medium. So send a harmless command, and if/when
- _that_ times out, we'll kick it in the head. */
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- 0, 0, NULL);
-
- lbs_deb_leave(LBS_DEB_TX);
-}
-
-void lbs_host_to_card_done(struct lbs_private *priv)
-{
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_THREAD);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- priv->dnld_sent = DNLD_RES_RECEIVED;
-
- /* Wake main thread if commands are pending */
- if (!priv->cur_cmd || priv->tx_pending_len > 0)
- wake_up_interruptible(&priv->waitq);
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_THREAD);
-}
-EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
-
-/**
- * @brief This function returns the network statistics
- *
- * @param dev A pointer to struct lbs_private structure
- * @return A pointer to net_device_stats structure
- */
-static struct net_device_stats *lbs_get_stats(struct net_device *dev)
-{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
-
- lbs_deb_enter(LBS_DEB_NET);
- return &priv->stats;
-}
-
-static int lbs_set_mac_address(struct net_device *dev, void *addr)
-{
- int ret = 0;
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
- struct sockaddr *phwaddr = addr;
- struct cmd_ds_802_11_mac_address cmd;
-
- lbs_deb_enter(LBS_DEB_NET);
-
- /* In case it was called from the mesh device */
- dev = priv->dev;
-
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_SET);
- memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
- if (ret) {
- lbs_deb_net("set MAC address failed\n");
- goto done;
- }
-
- memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
- memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
- if (priv->mesh_dev)
- memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
-
-done:
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
- return ret;
-}
-
-static int lbs_copy_multicast_address(struct lbs_private *priv,
- struct net_device *dev)
-{
- int i = 0;
- struct dev_mc_list *mcptr = dev->mc_list;
-
- for (i = 0; i < dev->mc_count; i++) {
- memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN);
- mcptr = mcptr->next;
- }
- return i;
-}
-
-static void lbs_set_multicast_list(struct net_device *dev)
-{
- struct lbs_private *priv = dev->priv;
- int old_mac_control;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_NET);
-
- old_mac_control = priv->mac_control;
-
- if (dev->flags & IFF_PROMISC) {
- lbs_deb_net("enable promiscuous mode\n");
- priv->mac_control |=
- CMD_ACT_MAC_PROMISCUOUS_ENABLE;
- priv->mac_control &=
- ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
- CMD_ACT_MAC_MULTICAST_ENABLE);
- } else {
- /* Multicast */
- priv->mac_control &=
- ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
-
- if (dev->flags & IFF_ALLMULTI || dev->mc_count >
- MRVDRV_MAX_MULTICAST_LIST_SIZE) {
- lbs_deb_net( "enabling all multicast\n");
- priv->mac_control |=
- CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
- priv->mac_control &=
- ~CMD_ACT_MAC_MULTICAST_ENABLE;
- } else {
- priv->mac_control &=
- ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
-
- if (!dev->mc_count) {
- lbs_deb_net("no multicast addresses, "
- "disabling multicast\n");
- priv->mac_control &=
- ~CMD_ACT_MAC_MULTICAST_ENABLE;
- } else {
- int i;
-
- priv->mac_control |=
- CMD_ACT_MAC_MULTICAST_ENABLE;
-
- priv->nr_of_multicastmacaddr =
- lbs_copy_multicast_address(priv, dev);
-
- lbs_deb_net("multicast addresses: %d\n",
- dev->mc_count);
-
- for (i = 0; i < dev->mc_count; i++) {
- lbs_deb_net("Multicast address %d: %s\n",
- i, print_mac(mac,
- priv->multicastlist[i]));
- }
- /* send multicast addresses to firmware */
- lbs_prepare_and_send_command(priv,
- CMD_MAC_MULTICAST_ADR,
- CMD_ACT_SET, 0, 0,
- NULL);
- }
- }
- }
-
- if (priv->mac_control != old_mac_control)
- lbs_set_mac_control(priv);
-
- lbs_deb_leave(LBS_DEB_NET);
-}
-
-/**
- * @brief This function handles the major jobs in the LBS driver.
- * It handles all events generated by firmware, RX data received
- * from firmware and TX data sent from kernel.
- *
- * @param data A pointer to lbs_thread structure
- * @return 0
- */
-static int lbs_thread(void *data)
-{
- struct net_device *dev = data;
- struct lbs_private *priv = dev->priv;
- wait_queue_t wait;
-
- lbs_deb_enter(LBS_DEB_THREAD);
-
- init_waitqueue_entry(&wait, current);
-
- for (;;) {
- int shouldsleep;
- u8 resp_idx;
-
- lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n",
- priv->currenttxskb, priv->dnld_sent);
-
- add_wait_queue(&priv->waitq, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irq(&priv->driver_lock);
-
- if (kthread_should_stop())
- shouldsleep = 0; /* Bye */
- else if (priv->surpriseremoved)
- shouldsleep = 1; /* We need to wait until we're _told_ to die */
- else if (priv->psstate == PS_STATE_SLEEP)
- shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */
- else if (priv->cmd_timed_out)
- shouldsleep = 0; /* Command timed out. Recover */
- else if (!priv->fw_ready)
- shouldsleep = 1; /* Firmware not ready. We're waiting for it */
- else if (priv->dnld_sent)
- shouldsleep = 1; /* Something is en route to the device already */
- else if (priv->tx_pending_len > 0)
- shouldsleep = 0; /* We've a packet to send */
- else if (priv->cur_cmd)
- shouldsleep = 1; /* Can't send a command; one already running */
- else if (!list_empty(&priv->cmdpendingq))
- shouldsleep = 0; /* We have a command to send */
- else if (__kfifo_len(priv->event_fifo))
- shouldsleep = 0; /* We have an event to process */
- else if (priv->resp_len[priv->resp_idx])
- shouldsleep = 0; /* We have a command response */
- else
- shouldsleep = 1; /* No command */
-
- if (shouldsleep) {
- lbs_deb_thread("sleeping, connect_status %d, "
- "ps_mode %d, ps_state %d\n",
- priv->connect_status,
- priv->psmode, priv->psstate);
- spin_unlock_irq(&priv->driver_lock);
- schedule();
- } else
- spin_unlock_irq(&priv->driver_lock);
-
- lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n",
- priv->currenttxskb, priv->dnld_sent);
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&priv->waitq, &wait);
-
- lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n",
- priv->currenttxskb, priv->dnld_sent);
-
- if (kthread_should_stop()) {
- lbs_deb_thread("break from main thread\n");
- break;
- }
-
- if (priv->surpriseremoved) {
- lbs_deb_thread("adapter removed; waiting to die...\n");
- continue;
- }
-
- lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n",
- priv->currenttxskb, priv->dnld_sent);
-
- /* Process any pending command response */
- spin_lock_irq(&priv->driver_lock);
- resp_idx = priv->resp_idx;
- if (priv->resp_len[resp_idx]) {
- spin_unlock_irq(&priv->driver_lock);
- lbs_process_command_response(priv,
- priv->resp_buf[resp_idx],
- priv->resp_len[resp_idx]);
- spin_lock_irq(&priv->driver_lock);
- priv->resp_len[resp_idx] = 0;
- }
- spin_unlock_irq(&priv->driver_lock);
-
- /* command timeout stuff */
- if (priv->cmd_timed_out && priv->cur_cmd) {
- struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
-
- if (++priv->nr_retries > 10) {
- lbs_pr_info("Excessive timeouts submitting command %x\n",
- le16_to_cpu(cmdnode->cmdbuf->command));
- lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
- priv->nr_retries = 0;
-#ifdef CONFIG_OLPC
- if (machine_is_olpc()) {
- spin_unlock_irq(&priv->driver_lock);
- printk(KERN_CRIT "Resetting OLPC wireless via EC...\n");
- olpc_ec_cmd(0x25, NULL, 0, NULL, 0);
- spin_lock_irq(&priv->driver_lock);
- }
-#endif
- } else {
- priv->cur_cmd = NULL;
- priv->dnld_sent = DNLD_RES_RECEIVED;
- lbs_pr_info("requeueing command %x due to timeout (#%d)\n",
- le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries);
-
- /* Stick it back at the _top_ of the pending queue
- for immediate resubmission */
- list_add(&cmdnode->list, &priv->cmdpendingq);
- }
- }
- priv->cmd_timed_out = 0;
-
- /* Process hardware events, e.g. card removed, link lost */
- spin_lock_irq(&priv->driver_lock);
- while (__kfifo_len(priv->event_fifo)) {
- u32 event;
-
- __kfifo_get(priv->event_fifo, (unsigned char *) &event,
- sizeof(event));
- spin_unlock_irq(&priv->driver_lock);
- lbs_process_event(priv, event);
- spin_lock_irq(&priv->driver_lock);
- }
- spin_unlock_irq(&priv->driver_lock);
-
- if (!priv->fw_ready)
- continue;
-
- /* Check if we need to confirm Sleep Request received previously */
- if (priv->psstate == PS_STATE_PRE_SLEEP &&
- !priv->dnld_sent && !priv->cur_cmd) {
- if (priv->connect_status == LBS_CONNECTED) {
- lbs_deb_thread("pre-sleep, currenttxskb %p, "
- "dnld_sent %d, cur_cmd %p\n",
- priv->currenttxskb, priv->dnld_sent,
- priv->cur_cmd);
-
- lbs_ps_confirm_sleep(priv);
- } else {
- /* workaround for firmware sending
- * deauth/linkloss event immediately
- * after sleep request; remove this
- * after firmware fixes it
- */
- priv->psstate = PS_STATE_AWAKE;
- lbs_pr_alert("ignore PS_SleepConfirm in "
- "non-connected state\n");
- }
- }
-
- /* The PS state is changed during processing of Sleep Request
- * event above
- */
- if ((priv->psstate == PS_STATE_SLEEP) ||
- (priv->psstate == PS_STATE_PRE_SLEEP))
- continue;
-
- /* Execute the next command */
- if (!priv->dnld_sent && !priv->cur_cmd)
- lbs_execute_next_command(priv);
-
- /* Wake-up command waiters which can't sleep in
- * lbs_prepare_and_send_command
- */
- if (!list_empty(&priv->cmdpendingq))
- wake_up_all(&priv->cmd_pending);
-
- spin_lock_irq(&priv->driver_lock);
- if (!priv->dnld_sent && priv->tx_pending_len > 0) {
- int ret = priv->hw_host_to_card(priv, MVMS_DAT,
- priv->tx_pending_buf,
- priv->tx_pending_len);
- if (ret) {
- lbs_deb_tx("host_to_card failed %d\n", ret);
- priv->dnld_sent = DNLD_RES_RECEIVED;
- }
- priv->tx_pending_len = 0;
- if (!priv->currenttxskb) {
- /* We can wake the queues immediately if we aren't
- waiting for TX feedback */
- if (priv->connect_status == LBS_CONNECTED)
- netif_wake_queue(priv->dev);
- if (priv->mesh_dev &&
- priv->mesh_connect_status == LBS_CONNECTED)
- netif_wake_queue(priv->mesh_dev);
- }
- }
- spin_unlock_irq(&priv->driver_lock);
- }
-
- del_timer(&priv->command_timer);
- wake_up_all(&priv->cmd_pending);
-
- lbs_deb_leave(LBS_DEB_THREAD);
- return 0;
-}
-
-static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy,
- struct cmd_header *cmd)
-{
- lbs_deb_enter(LBS_DEB_FW);
-
- netif_device_detach(priv->dev);
- if (priv->mesh_dev)
- netif_device_detach(priv->mesh_dev);
-
- priv->fw_ready = 0;
- lbs_deb_leave(LBS_DEB_FW);
- return 0;
-}
-
-int lbs_suspend(struct lbs_private *priv)
-{
- struct cmd_header cmd;
- int ret;
-
- lbs_deb_enter(LBS_DEB_FW);
-
- if (priv->wol_criteria == 0xffffffff) {
- lbs_pr_info("Suspend attempt without configuring wake params!\n");
- return -EINVAL;
- }
-
- memset(&cmd, 0, sizeof(cmd));
-
- ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
- sizeof(cmd), lbs_suspend_callback, 0);
- if (ret)
- lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
-
- lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
- return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_suspend);
-
-int lbs_resume(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_FW);
-
- priv->fw_ready = 1;
-
- /* Firmware doesn't seem to give us RX packets any more
- until we send it some command. Might as well update */
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- 0, 0, NULL);
-
- netif_device_attach(priv->dev);
- if (priv->mesh_dev)
- netif_device_attach(priv->mesh_dev);
-
- lbs_deb_leave(LBS_DEB_FW);
- return 0;
-}
-EXPORT_SYMBOL_GPL(lbs_resume);
-
-/**
- * @brief This function downloads firmware image, gets
- * HW spec from firmware and set basic parameters to
- * firmware.
- *
- * @param priv A pointer to struct lbs_private structure
- * @return 0 or -1
- */
-static int lbs_setup_firmware(struct lbs_private *priv)
-{
- int ret = -1;
-
- lbs_deb_enter(LBS_DEB_FW);
-
- /*
- * Read MAC address from HW
- */
- memset(priv->current_addr, 0xff, ETH_ALEN);
- ret = lbs_update_hw_spec(priv);
- if (ret) {
- ret = -1;
- goto done;
- }
-
- lbs_set_mac_control(priv);
-
- ret = lbs_get_data_rate(priv);
- if (ret < 0) {
- ret = -1;
- goto done;
- }
-
- ret = 0;
-done:
- lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
- return ret;
-}
-
-/**
- * This function handles the timeout of command sending.
- * It will re-send the same command again.
- */
-static void command_timer_fn(unsigned long data)
-{
- struct lbs_private *priv = (struct lbs_private *)data;
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_CMD);
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (!priv->cur_cmd) {
- lbs_pr_info("Command timer expired; no pending command\n");
- goto out;
- }
-
- lbs_pr_info("Command %x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command));
-
- priv->cmd_timed_out = 1;
- wake_up_interruptible(&priv->waitq);
-out:
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_CMD);
-}
-
-static void lbs_sync_channel_worker(struct work_struct *work)
-{
- struct lbs_private *priv = container_of(work, struct lbs_private,
- sync_channel);
-
- lbs_deb_enter(LBS_DEB_MAIN);
- if (lbs_update_channel(priv))
- lbs_pr_info("Channel synchronization failed.");
- lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-
-static int lbs_init_adapter(struct lbs_private *priv)
-{
- size_t bufsize;
- int i, ret = 0;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- /* Allocate buffer to store the BSSID list */
- bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
- priv->networks = kzalloc(bufsize, GFP_KERNEL);
- if (!priv->networks) {
- lbs_pr_err("Out of memory allocating beacons\n");
- ret = -1;
- goto out;
- }
-
- /* Initialize scan result lists */
- INIT_LIST_HEAD(&priv->network_free_list);
- INIT_LIST_HEAD(&priv->network_list);
- for (i = 0; i < MAX_NETWORK_COUNT; i++) {
- list_add_tail(&priv->networks[i].list,
- &priv->network_free_list);
- }
-
- memset(priv->current_addr, 0xff, ETH_ALEN);
-
- priv->connect_status = LBS_DISCONNECTED;
- priv->mesh_connect_status = LBS_DISCONNECTED;
- priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- priv->mode = IW_MODE_INFRA;
- priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
- priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
- priv->radioon = RADIO_ON;
- priv->auto_rate = 1;
- priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
- priv->psmode = LBS802_11POWERMODECAM;
- priv->psstate = PS_STATE_FULL_POWER;
-
- mutex_init(&priv->lock);
-
- setup_timer(&priv->command_timer, command_timer_fn,
- (unsigned long)priv);
-
- INIT_LIST_HEAD(&priv->cmdfreeq);
- INIT_LIST_HEAD(&priv->cmdpendingq);
-
- spin_lock_init(&priv->driver_lock);
- init_waitqueue_head(&priv->cmd_pending);
-
- /* Allocate the command buffers */
- if (lbs_allocate_cmd_buffer(priv)) {
- lbs_pr_err("Out of memory allocating command buffers\n");
- ret = -ENOMEM;
- goto out;
- }
- priv->resp_idx = 0;
- priv->resp_len[0] = priv->resp_len[1] = 0;
-
- /* Create the event FIFO */
- priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL);
- if (IS_ERR(priv->event_fifo)) {
- lbs_pr_err("Out of memory allocating event FIFO buffer\n");
- ret = -ENOMEM;
- goto out;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
-
- return ret;
-}
-
-static void lbs_free_adapter(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_MAIN);
-
- lbs_free_cmd_buffer(priv);
- if (priv->event_fifo)
- kfifo_free(priv->event_fifo);
- del_timer(&priv->command_timer);
- kfree(priv->networks);
- priv->networks = NULL;
-
- lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-/**
- * @brief This function adds the card. it will probe the
- * card, allocate the lbs_priv and initialize the device.
- *
- * @param card A pointer to card
- * @return A pointer to struct lbs_private structure
- */
-struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
-{
- struct net_device *dev = NULL;
- struct lbs_private *priv = NULL;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- /* Allocate an Ethernet device and register it */
- dev = alloc_etherdev(sizeof(struct lbs_private));
- if (!dev) {
- lbs_pr_err("init ethX device failed\n");
- goto done;
- }
- priv = dev->priv;
-
- if (lbs_init_adapter(priv)) {
- lbs_pr_err("failed to initialize adapter structure.\n");
- goto err_init_adapter;
- }
-
- priv->dev = dev;
- priv->card = card;
- priv->mesh_open = 0;
- priv->infra_open = 0;
-
- /* Setup the OS Interface to our functions */
- dev->open = lbs_dev_open;
- dev->hard_start_xmit = lbs_hard_start_xmit;
- dev->stop = lbs_eth_stop;
- dev->set_mac_address = lbs_set_mac_address;
- dev->tx_timeout = lbs_tx_timeout;
- dev->do_ioctl = lbs_do_ioctl;
- dev->get_stats = lbs_get_stats;
- dev->watchdog_timeo = 5 * HZ;
- dev->ethtool_ops = &lbs_ethtool_ops;
-#ifdef WIRELESS_EXT
- dev->wireless_handlers = (struct iw_handler_def *)&lbs_handler_def;
-#endif
- dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- dev->set_multicast_list = lbs_set_multicast_list;
-
- SET_NETDEV_DEV(dev, dmdev);
-
- priv->rtap_net_dev = NULL;
-
- lbs_deb_thread("Starting main thread...\n");
- init_waitqueue_head(&priv->waitq);
- priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
- if (IS_ERR(priv->main_thread)) {
- lbs_deb_thread("Error creating main thread.\n");
- goto err_init_adapter;
- }
-
- priv->work_thread = create_singlethread_workqueue("lbs_worker");
- INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
- INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
- INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
-
- sprintf(priv->mesh_ssid, "mesh");
- priv->mesh_ssid_len = 4;
-
- priv->wol_criteria = 0xffffffff;
- priv->wol_gpio = 0xff;
-
- goto done;
-
-err_init_adapter:
- lbs_free_adapter(priv);
- free_netdev(dev);
- priv = NULL;
-
-done:
- lbs_deb_leave_args(LBS_DEB_MAIN, "priv %p", priv);
- return priv;
-}
-EXPORT_SYMBOL_GPL(lbs_add_card);
-
-
-int lbs_remove_card(struct lbs_private *priv)
-{
- struct net_device *dev = priv->dev;
- union iwreq_data wrqu;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- lbs_remove_mesh(priv);
- lbs_remove_rtap(priv);
-
- dev = priv->dev;
-
- cancel_delayed_work(&priv->scan_work);
- cancel_delayed_work(&priv->assoc_work);
- destroy_workqueue(priv->work_thread);
-
- if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
- priv->psmode = LBS802_11POWERMODECAM;
- lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
- }
-
- memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
- /* Stop the thread servicing the interrupts */
- priv->surpriseremoved = 1;
- kthread_stop(priv->main_thread);
-
- lbs_free_adapter(priv);
-
- priv->dev = NULL;
- free_netdev(dev);
-
- lbs_deb_leave(LBS_DEB_MAIN);
- return 0;
-}
-EXPORT_SYMBOL_GPL(lbs_remove_card);
-
-
-int lbs_start_card(struct lbs_private *priv)
-{
- struct net_device *dev = priv->dev;
- int ret = -1;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- /* poke the firmware */
- ret = lbs_setup_firmware(priv);
- if (ret)
- goto done;
-
- /* init 802.11d */
- lbs_init_11d(priv);
-
- if (register_netdev(dev)) {
- lbs_pr_err("cannot register ethX device\n");
- goto done;
- }
- if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
- lbs_pr_err("cannot register lbs_rtap attribute\n");
-
- lbs_update_channel(priv);
-
- /* 5.0.16p0 is known to NOT support any mesh */
- if (priv->fwrelease > 0x05001000) {
- /* Enable mesh, if supported, and work out which TLV it uses.
- 0x100 + 291 is an unofficial value used in 5.110.20.pXX
- 0x100 + 37 is the official value used in 5.110.21.pXX
- but we check them in that order because 20.pXX doesn't
- give an error -- it just silently fails. */
-
- /* 5.110.20.pXX firmware will fail the command if the channel
- doesn't match the existing channel. But only if the TLV
- is correct. If the channel is wrong, _BOTH_ versions will
- give an error to 0x100+291, and allow 0x100+37 to succeed.
- It's just that 5.110.20.pXX will not have done anything
- useful */
-
- priv->mesh_tlv = 0x100 + 291;
- if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) {
- priv->mesh_tlv = 0x100 + 37;
- if (lbs_mesh_config(priv, 1, priv->curbssparams.channel))
- priv->mesh_tlv = 0;
- }
- if (priv->mesh_tlv) {
- lbs_add_mesh(priv);
-
- if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
- lbs_pr_err("cannot register lbs_mesh attribute\n");
- }
- }
-
- lbs_debugfs_init_one(priv, dev);
-
- lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
-
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
- return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_start_card);
-
-
-int lbs_stop_card(struct lbs_private *priv)
-{
- struct net_device *dev = priv->dev;
- int ret = -1;
- struct cmd_ctrl_node *cmdnode;
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
-
- lbs_debugfs_remove_one(priv);
- device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
- if (priv->mesh_tlv)
- device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
-
- /* Flush pending command nodes */
- spin_lock_irqsave(&priv->driver_lock, flags);
- list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
- cmdnode->result = -ENOENT;
- cmdnode->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmdnode->cmdwait_q);
- }
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- unregister_netdev(dev);
-
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
- return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_stop_card);
-
-
-/**
- * @brief This function adds mshX interface
- *
- * @param priv A pointer to the struct lbs_private structure
- * @return 0 if successful, -X otherwise
- */
-static int lbs_add_mesh(struct lbs_private *priv)
-{
- struct net_device *mesh_dev = NULL;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_MESH);
-
- /* Allocate a virtual mesh device */
- if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
- lbs_deb_mesh("init mshX device failed\n");
- ret = -ENOMEM;
- goto done;
- }
- mesh_dev->priv = priv;
- priv->mesh_dev = mesh_dev;
-
- mesh_dev->open = lbs_dev_open;
- mesh_dev->hard_start_xmit = lbs_hard_start_xmit;
- mesh_dev->stop = lbs_mesh_stop;
- mesh_dev->do_ioctl = lbs_do_ioctl;
- mesh_dev->get_stats = lbs_get_stats;
- mesh_dev->set_mac_address = lbs_set_mac_address;
- mesh_dev->ethtool_ops = &lbs_ethtool_ops;
- memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
- sizeof(priv->dev->dev_addr));
-
- SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
-
-#ifdef WIRELESS_EXT
- mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
-#endif
- /* Register virtual mesh interface */
- ret = register_netdev(mesh_dev);
- if (ret) {
- lbs_pr_err("cannot register mshX virtual interface\n");
- goto err_free;
- }
-
- ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
- if (ret)
- goto err_unregister;
-
- /* Everything successful */
- ret = 0;
- goto done;
-
-err_unregister:
- unregister_netdev(mesh_dev);
-
-err_free:
- free_netdev(mesh_dev);
-
-done:
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
-
-static void lbs_remove_mesh(struct lbs_private *priv)
-{
- struct net_device *mesh_dev;
-
-
- mesh_dev = priv->mesh_dev;
- if (!mesh_dev)
- return;
-
- lbs_deb_enter(LBS_DEB_MESH);
- netif_stop_queue(mesh_dev);
- netif_carrier_off(priv->mesh_dev);
- sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
- unregister_netdev(mesh_dev);
- priv->mesh_dev = NULL;
- free_netdev(mesh_dev);
- lbs_deb_leave(LBS_DEB_MESH);
-}
-
-/**
- * @brief This function finds the CFP in
- * region_cfp_table based on region and band parameter.
- *
- * @param region The region code
- * @param band The band
- * @param cfp_no A pointer to CFP number
- * @return A pointer to CFP
- */
-struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
-{
- int i, end;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- end = ARRAY_SIZE(region_cfp_table);
-
- for (i = 0; i < end ; i++) {
- lbs_deb_main("region_cfp_table[i].region=%d\n",
- region_cfp_table[i].region);
- if (region_cfp_table[i].region == region) {
- *cfp_no = region_cfp_table[i].cfp_no_BG;
- lbs_deb_leave(LBS_DEB_MAIN);
- return region_cfp_table[i].cfp_BG;
- }
- }
-
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
- return NULL;
-}
-
-int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
-{
- int ret = 0;
- int i = 0;
-
- struct chan_freq_power *cfp;
- int cfp_no;
-
- lbs_deb_enter(LBS_DEB_MAIN);
-
- memset(priv->region_channel, 0, sizeof(priv->region_channel));
-
- cfp = lbs_get_region_cfp_table(region, &cfp_no);
- if (cfp != NULL) {
- priv->region_channel[i].nrcfp = cfp_no;
- priv->region_channel[i].CFP = cfp;
- } else {
- lbs_deb_main("wrong region code %#x in band B/G\n",
- region);
- ret = -1;
- goto out;
- }
- priv->region_channel[i].valid = 1;
- priv->region_channel[i].region = region;
- priv->region_channel[i].band = band;
- i++;
-out:
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
- return ret;
-}
-
-void lbs_queue_event(struct lbs_private *priv, u32 event)
-{
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_THREAD);
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (priv->psstate == PS_STATE_SLEEP)
- priv->psstate = PS_STATE_AWAKE;
-
- __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32));
-
- wake_up_interruptible(&priv->waitq);
-
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_THREAD);
-}
-EXPORT_SYMBOL_GPL(lbs_queue_event);
-
-void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
-{
- lbs_deb_enter(LBS_DEB_THREAD);
-
- if (priv->psstate == PS_STATE_SLEEP)
- priv->psstate = PS_STATE_AWAKE;
-
- /* Swap buffers by flipping the response index */
- BUG_ON(resp_idx > 1);
- priv->resp_idx = resp_idx;
-
- wake_up_interruptible(&priv->waitq);
-
- lbs_deb_leave(LBS_DEB_THREAD);
-}
-EXPORT_SYMBOL_GPL(lbs_notify_command_response);
-
-static int __init lbs_init_module(void)
-{
- lbs_deb_enter(LBS_DEB_MAIN);
- memset(&confirm_sleep, 0, sizeof(confirm_sleep));
- confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
- confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
- confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
- lbs_debugfs_init();
- lbs_deb_leave(LBS_DEB_MAIN);
- return 0;
-}
-
-static void __exit lbs_exit_module(void)
-{
- lbs_deb_enter(LBS_DEB_MAIN);
- lbs_debugfs_remove();
- lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-/*
- * rtap interface support fuctions
- */
-
-static int lbs_rtap_open(struct net_device *dev)
-{
- /* Yes, _stop_ the queue. Because we don't support injection */
- lbs_deb_enter(LBS_DEB_MAIN);
- netif_carrier_off(dev);
- netif_stop_queue(dev);
- lbs_deb_leave(LBS_DEB_LEAVE);
- return 0;
-}
-
-static int lbs_rtap_stop(struct net_device *dev)
-{
- lbs_deb_enter(LBS_DEB_MAIN);
- lbs_deb_leave(LBS_DEB_MAIN);
- return 0;
-}
-
-static int lbs_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- netif_stop_queue(dev);
- return NETDEV_TX_BUSY;
-}
-
-static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
-{
- struct lbs_private *priv = dev->priv;
- lbs_deb_enter(LBS_DEB_NET);
- return &priv->stats;
-}
-
-
-static void lbs_remove_rtap(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_MAIN);
- if (priv->rtap_net_dev == NULL)
- return;
- unregister_netdev(priv->rtap_net_dev);
- free_netdev(priv->rtap_net_dev);
- priv->rtap_net_dev = NULL;
- lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-static int lbs_add_rtap(struct lbs_private *priv)
-{
- int ret = 0;
- struct net_device *rtap_dev;
-
- lbs_deb_enter(LBS_DEB_MAIN);
- if (priv->rtap_net_dev) {
- ret = -EPERM;
- goto out;
- }
-
- rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
- if (rtap_dev == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
- rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
- rtap_dev->open = lbs_rtap_open;
- rtap_dev->stop = lbs_rtap_stop;
- rtap_dev->get_stats = lbs_rtap_get_stats;
- rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
- rtap_dev->set_multicast_list = lbs_set_multicast_list;
- rtap_dev->priv = priv;
- SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
-
- ret = register_netdev(rtap_dev);
- if (ret) {
- free_netdev(rtap_dev);
- goto out;
- }
- priv->rtap_net_dev = rtap_dev;
-
-out:
- lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
- return ret;
-}
-
-#ifndef CONFIG_IEEE80211
-const char *escape_essid(const char *essid, u8 essid_len)
-{
- static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
-
- if (ieee80211_is_empty_essid(essid, essid_len)) {
- memcpy(escaped, "<hidden>", sizeof("<hidden>"));
- return escaped;
- }
-
- essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else {
- *d++ = *s++;
- }
- }
- *d = '\0';
- return escaped;
-}
-#endif
-
-module_init(lbs_init_module);
-module_exit(lbs_exit_module);
-
-MODULE_DESCRIPTION("Libertas WLAN Driver Library");
-MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_LICENSE("GPL");
+++ /dev/null
-#include <net/ieee80211_radiotap.h>
-
-struct tx_radiotap_hdr {
- struct ieee80211_radiotap_header hdr;
- u8 rate;
- u8 txpower;
- u8 rts_retries;
- u8 data_retries;
-#if 0
- u8 pad[IEEE80211_RADIOTAP_HDRLEN - 12];
-#endif
-} __attribute__ ((packed));
-
-#define TX_RADIOTAP_PRESENT ( \
- (1 << IEEE80211_RADIOTAP_RATE) | \
- (1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \
- (1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \
- (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | \
- 0)
-
-#define IEEE80211_FC_VERSION_MASK 0x0003
-#define IEEE80211_FC_TYPE_MASK 0x000c
-#define IEEE80211_FC_TYPE_MGT 0x0000
-#define IEEE80211_FC_TYPE_CTL 0x0004
-#define IEEE80211_FC_TYPE_DATA 0x0008
-#define IEEE80211_FC_SUBTYPE_MASK 0x00f0
-#define IEEE80211_FC_TOFROMDS_MASK 0x0300
-#define IEEE80211_FC_TODS_MASK 0x0100
-#define IEEE80211_FC_FROMDS_MASK 0x0200
-#define IEEE80211_FC_NODS 0x0000
-#define IEEE80211_FC_TODS 0x0100
-#define IEEE80211_FC_FROMDS 0x0200
-#define IEEE80211_FC_DSTODS 0x0300
-
-struct rx_radiotap_hdr {
- struct ieee80211_radiotap_header hdr;
- u8 flags;
- u8 rate;
- u16 chan_freq;
- u16 chan_flags;
- u8 antenna;
- u8 antsignal;
- u16 rx_flags;
-#if 0
- u8 pad[IEEE80211_RADIOTAP_HDRLEN - 18];
-#endif
-} __attribute__ ((packed));
-
-#define RX_RADIOTAP_PRESENT ( \
- (1 << IEEE80211_RADIOTAP_FLAGS) | \
- (1 << IEEE80211_RADIOTAP_RATE) | \
- (1 << IEEE80211_RADIOTAP_CHANNEL) | \
- (1 << IEEE80211_RADIOTAP_ANTENNA) | \
- (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |\
- (1 << IEEE80211_RADIOTAP_RX_FLAGS) | \
- 0)
-
+++ /dev/null
-/**
- * This file contains the handling of RX in wlan driver.
- */
-#include <linux/etherdevice.h>
-#include <linux/types.h>
-
-#include "hostcmd.h"
-#include "radiotap.h"
-#include "decl.h"
-#include "dev.h"
-#include "wext.h"
-
-struct eth803hdr {
- u8 dest_addr[6];
- u8 src_addr[6];
- u16 h803_len;
-} __attribute__ ((packed));
-
-struct rfc1042hdr {
- u8 llc_dsap;
- u8 llc_ssap;
- u8 llc_ctrl;
- u8 snap_oui[3];
- u16 snap_type;
-} __attribute__ ((packed));
-
-struct rxpackethdr {
- struct rxpd rx_pd;
- struct eth803hdr eth803_hdr;
- struct rfc1042hdr rfc1042_hdr;
-} __attribute__ ((packed));
-
-struct rx80211packethdr {
- struct rxpd rx_pd;
- void *eth80211_hdr;
-} __attribute__ ((packed));
-
-static int process_rxed_802_11_packet(struct lbs_private *priv,
- struct sk_buff *skb);
-
-/**
- * @brief This function computes the avgSNR .
- *
- * @param priv A pointer to struct lbs_private structure
- * @return avgSNR
- */
-static u8 lbs_getavgsnr(struct lbs_private *priv)
-{
- u8 i;
- u16 temp = 0;
- if (priv->numSNRNF == 0)
- return 0;
- for (i = 0; i < priv->numSNRNF; i++)
- temp += priv->rawSNR[i];
- return (u8) (temp / priv->numSNRNF);
-
-}
-
-/**
- * @brief This function computes the AvgNF
- *
- * @param priv A pointer to struct lbs_private structure
- * @return AvgNF
- */
-static u8 lbs_getavgnf(struct lbs_private *priv)
-{
- u8 i;
- u16 temp = 0;
- if (priv->numSNRNF == 0)
- return 0;
- for (i = 0; i < priv->numSNRNF; i++)
- temp += priv->rawNF[i];
- return (u8) (temp / priv->numSNRNF);
-
-}
-
-/**
- * @brief This function save the raw SNR/NF to our internel buffer
- *
- * @param priv A pointer to struct lbs_private structure
- * @param prxpd A pointer to rxpd structure of received packet
- * @return n/a
- */
-static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
-{
- if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
- priv->numSNRNF++;
- priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
- priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
- priv->nextSNRNF++;
- if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
- priv->nextSNRNF = 0;
- return;
-}
-
-/**
- * @brief This function computes the RSSI in received packet.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param prxpd A pointer to rxpd structure of received packet
- * @return n/a
- */
-static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
-{
-
- lbs_deb_enter(LBS_DEB_RX);
-
- lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
- lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
- priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
- priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
- priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
- lbs_save_rawSNRNF(priv, p_rx_pd);
-
- priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
- priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
- lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
- priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
- priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
- CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
- priv->NF[TYPE_RXPD][TYPE_NOAVG]);
-
- priv->RSSI[TYPE_RXPD][TYPE_AVG] =
- CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
- lbs_deb_leave(LBS_DEB_RX);
-}
-
-/**
- * @brief This function processes received packet and forwards it
- * to kernel/upper layer
- *
- * @param priv A pointer to struct lbs_private
- * @param skb A pointer to skb which includes the received packet
- * @return 0 or -1
- */
-int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
-{
- int ret = 0;
- struct net_device *dev = priv->dev;
- struct rxpackethdr *p_rx_pkt;
- struct rxpd *p_rx_pd;
- int hdrchop;
- struct ethhdr *p_ethhdr;
- const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-
- lbs_deb_enter(LBS_DEB_RX);
-
- BUG_ON(!skb);
-
- skb->ip_summed = CHECKSUM_NONE;
-
- if (priv->monitormode)
- return process_rxed_802_11_packet(priv, skb);
-
- p_rx_pkt = (struct rxpackethdr *) skb->data;
- p_rx_pd = &p_rx_pkt->rx_pd;
- if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME))
- dev = priv->mesh_dev;
-
- lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
- min_t(unsigned int, skb->len, 100));
-
- if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
- lbs_deb_rx("rx err: frame received with bad length\n");
- priv->stats.rx_length_errors++;
- ret = 0;
- goto done;
- }
-
- /*
- * Check rxpd status and update 802.3 stat,
- */
- if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
- lbs_deb_rx("rx err: frame received with bad status\n");
- lbs_pr_alert("rxpd not ok\n");
- priv->stats.rx_errors++;
- ret = 0;
- goto done;
- }
-
- lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
- skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
-
- lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
- sizeof(p_rx_pkt->eth803_hdr.dest_addr));
- lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr,
- sizeof(p_rx_pkt->eth803_hdr.src_addr));
-
- if (memcmp(&p_rx_pkt->rfc1042_hdr,
- rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
- /*
- * Replace the 803 header and rfc1042 header (llc/snap) with an
- * EthernetII header, keep the src/dst and snap_type (ethertype)
- *
- * The firmware only passes up SNAP frames converting
- * all RX Data from 802.11 to 802.2/LLC/SNAP frames.
- *
- * To create the Ethernet II, just move the src, dst address right
- * before the snap_type.
- */
- p_ethhdr = (struct ethhdr *)
- ((u8 *) & p_rx_pkt->eth803_hdr
- + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
- - sizeof(p_rx_pkt->eth803_hdr.dest_addr)
- - sizeof(p_rx_pkt->eth803_hdr.src_addr)
- - sizeof(p_rx_pkt->rfc1042_hdr.snap_type));
-
- memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr,
- sizeof(p_ethhdr->h_source));
- memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr,
- sizeof(p_ethhdr->h_dest));
-
- /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header
- * that was removed
- */
- hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt;
- } else {
- lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
- (u8 *) & p_rx_pkt->rfc1042_hdr,
- sizeof(p_rx_pkt->rfc1042_hdr));
-
- /* Chop off the rxpd */
- hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt;
- }
-
- /* Chop off the leading header bytes so the skb points to the start of
- * either the reconstructed EthII frame or the 802.2/llc/snap frame
- */
- skb_pull(skb, hdrchop);
-
- /* Take the data rate from the rxpd structure
- * only if the rate is auto
- */
- if (priv->auto_rate)
- priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
-
- lbs_compute_rssi(priv, p_rx_pd);
-
- lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
- priv->stats.rx_bytes += skb->len;
- priv->stats.rx_packets++;
-
- skb->protocol = eth_type_trans(skb, dev);
- if (in_interrupt())
- netif_rx(skb);
- else
- netif_rx_ni(skb);
-
- ret = 0;
-done:
- lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
- return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
-
-/**
- * @brief This function converts Tx/Rx rates from the Marvell WLAN format
- * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
- *
- * @param rate Input rate
- * @return Output Rate (0 if invalid)
- */
-static u8 convert_mv_rate_to_radiotap(u8 rate)
-{
- switch (rate) {
- case 0: /* 1 Mbps */
- return 2;
- case 1: /* 2 Mbps */
- return 4;
- case 2: /* 5.5 Mbps */
- return 11;
- case 3: /* 11 Mbps */
- return 22;
- /* case 4: reserved */
- case 5: /* 6 Mbps */
- return 12;
- case 6: /* 9 Mbps */
- return 18;
- case 7: /* 12 Mbps */
- return 24;
- case 8: /* 18 Mbps */
- return 36;
- case 9: /* 24 Mbps */
- return 48;
- case 10: /* 36 Mbps */
- return 72;
- case 11: /* 48 Mbps */
- return 96;
- case 12: /* 54 Mbps */
- return 108;
- }
- lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate);
- return 0;
-}
-
-/**
- * @brief This function processes a received 802.11 packet and forwards it
- * to kernel/upper layer
- *
- * @param priv A pointer to struct lbs_private
- * @param skb A pointer to skb which includes the received packet
- * @return 0 or -1
- */
-static int process_rxed_802_11_packet(struct lbs_private *priv,
- struct sk_buff *skb)
-{
- int ret = 0;
-
- struct rx80211packethdr *p_rx_pkt;
- struct rxpd *prxpd;
- struct rx_radiotap_hdr radiotap_hdr;
- struct rx_radiotap_hdr *pradiotap_hdr;
-
- lbs_deb_enter(LBS_DEB_RX);
-
- p_rx_pkt = (struct rx80211packethdr *) skb->data;
- prxpd = &p_rx_pkt->rx_pd;
-
- // lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
-
- if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
- lbs_deb_rx("rx err: frame received with bad length\n");
- priv->stats.rx_length_errors++;
- ret = -EINVAL;
- kfree(skb);
- goto done;
- }
-
- /*
- * Check rxpd status and update 802.3 stat,
- */
- if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
- //lbs_deb_rx("rx err: frame received with bad status\n");
- priv->stats.rx_errors++;
- }
-
- lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
- skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
-
- /* create the exported radio header */
-
- /* radiotap header */
- radiotap_hdr.hdr.it_version = 0;
- /* XXX must check this value for pad */
- radiotap_hdr.hdr.it_pad = 0;
- radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
- radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
- /* unknown values */
- radiotap_hdr.flags = 0;
- radiotap_hdr.chan_freq = 0;
- radiotap_hdr.chan_flags = 0;
- radiotap_hdr.antenna = 0;
- /* known values */
- radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
- /* XXX must check no carryout */
- radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
- radiotap_hdr.rx_flags = 0;
- if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
- radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
- //memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
-
- /* chop the rxpd */
- skb_pull(skb, sizeof(struct rxpd));
-
- /* add space for the new radio header */
- if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
- pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) {
- lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__);
- ret = -ENOMEM;
- kfree_skb(skb);
- goto done;
- }
-
- pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
- memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
-
- /* Take the data rate from the rxpd structure
- * only if the rate is auto
- */
- if (priv->auto_rate)
- priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
-
- lbs_compute_rssi(priv, prxpd);
-
- lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
- priv->stats.rx_bytes += skb->len;
- priv->stats.rx_packets++;
-
- skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
- netif_rx(skb);
-
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
- return ret;
-}
+++ /dev/null
-/**
- * Functions implementing wlan scan IOCTL and firmware command APIs
- *
- * IOCTL handlers as well as command preperation and response routines
- * for sending scan commands to the firmware.
- */
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "host.h"
-#include "decl.h"
-#include "dev.h"
-#include "scan.h"
-#include "cmd.h"
-
-//! Approximate amount of data needed to pass a scan result back to iwlist
-#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
- + IW_ESSID_MAX_SIZE \
- + IW_EV_UINT_LEN \
- + IW_EV_FREQ_LEN \
- + IW_EV_QUAL_LEN \
- + IW_ESSID_MAX_SIZE \
- + IW_EV_PARAM_LEN \
- + 40) /* 40 for WPAIE */
-
-//! Memory needed to store a max sized channel List TLV for a firmware scan
-#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvlietypesheader) \
- + (MRVDRV_MAX_CHANNELS_PER_SCAN \
- * sizeof(struct chanscanparamset)))
-
-//! Memory needed to store a max number/size SSID TLV for a firmware scan
-#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset))
-
-//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
-#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \
- + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
-
-//! The maximum number of channels the firmware can scan per command
-#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
-
-/**
- * @brief Number of channels to scan per firmware scan command issuance.
- *
- * Number restricted to prevent hitting the limit on the amount of scan data
- * returned in a single firmware scan command.
- */
-#define MRVDRV_CHANNELS_PER_SCAN_CMD 4
-
-//! Scan time specified in the channel TLV for each channel for passive scans
-#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100
-
-//! Scan time specified in the channel TLV for each channel for active scans
-#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
-
-static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
- struct cmd_header *resp);
-
-/*********************************************************************/
-/* */
-/* Misc helper functions */
-/* */
-/*********************************************************************/
-
-/**
- * @brief Unsets the MSB on basic rates
- *
- * Scan through an array and unset the MSB for basic data rates.
- *
- * @param rates buffer of data rates
- * @param len size of buffer
- */
-static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- rates[i] &= 0x7f;
-}
-
-
-static inline void clear_bss_descriptor(struct bss_descriptor *bss)
-{
- /* Don't blow away ->list, just BSS data */
- memset(bss, 0, offsetof(struct bss_descriptor, list));
-}
-
-/**
- * @brief Compare two SSIDs
- *
- * @param ssid1 A pointer to ssid to compare
- * @param ssid2 A pointer to ssid to compare
- *
- * @return 0: ssid is same, otherwise is different
- */
-int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
- uint8_t ssid2_len)
-{
- if (ssid1_len != ssid2_len)
- return -1;
-
- return memcmp(ssid1, ssid2, ssid1_len);
-}
-
-static inline int is_same_network(struct bss_descriptor *src,
- struct bss_descriptor *dst)
-{
- /* A network is only a duplicate if the channel, BSSID, and ESSID
- * all match. We treat all <hidden> with the same BSSID and channel
- * as one network */
- return ((src->ssid_len == dst->ssid_len) &&
- (src->channel == dst->channel) &&
- !compare_ether_addr(src->bssid, dst->bssid) &&
- !memcmp(src->ssid, dst->ssid, src->ssid_len));
-}
-
-
-
-
-/*********************************************************************/
-/* */
-/* Main scanning support */
-/* */
-/*********************************************************************/
-
-/**
- * @brief Create a channel list for the driver to scan based on region info
- *
- * Only used from lbs_scan_setup_scan_config()
- *
- * Use the driver region/band information to construct a comprehensive list
- * of channels to scan. This routine is used for any scan that is not
- * provided a specific channel list to scan.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param scanchanlist Output parameter: resulting channel list to scan
- *
- * @return void
- */
-static int lbs_scan_create_channel_list(struct lbs_private *priv,
- struct chanscanparamset *scanchanlist)
-{
- struct region_channel *scanregion;
- struct chan_freq_power *cfp;
- int rgnidx;
- int chanidx;
- int nextchan;
- uint8_t scantype;
-
- chanidx = 0;
-
- /* Set the default scan type to the user specified type, will later
- * be changed to passive on a per channel basis if restricted by
- * regulatory requirements (11d or 11h)
- */
- scantype = CMD_SCAN_TYPE_ACTIVE;
-
- for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
- if (priv->enable11d && (priv->connect_status != LBS_CONNECTED)
- && (priv->mesh_connect_status != LBS_CONNECTED)) {
- /* Scan all the supported chan for the first scan */
- if (!priv->universal_channel[rgnidx].valid)
- continue;
- scanregion = &priv->universal_channel[rgnidx];
-
- /* clear the parsed_region_chan for the first scan */
- memset(&priv->parsed_region_chan, 0x00,
- sizeof(priv->parsed_region_chan));
- } else {
- if (!priv->region_channel[rgnidx].valid)
- continue;
- scanregion = &priv->region_channel[rgnidx];
- }
-
- for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
- struct chanscanparamset *chan = &scanchanlist[chanidx];
-
- cfp = scanregion->CFP + nextchan;
-
- if (priv->enable11d)
- scantype = lbs_get_scan_type_11d(cfp->channel,
- &priv->parsed_region_chan);
-
- if (scanregion->band == BAND_B || scanregion->band == BAND_G)
- chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
-
- if (scantype == CMD_SCAN_TYPE_PASSIVE) {
- chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
- chan->chanscanmode.passivescan = 1;
- } else {
- chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
- chan->chanscanmode.passivescan = 0;
- }
-
- chan->channumber = cfp->channel;
- }
- }
- return chanidx;
-}
-
-/*
- * Add SSID TLV of the form:
- *
- * TLV-ID SSID 00 00
- * length 06 00
- * ssid 4d 4e 54 45 53 54
- */
-static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
-{
- struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
-
- ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
- ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
- memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
- return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
-}
-
-/*
- * Add CHANLIST TLV of the form
- *
- * TLV-ID CHANLIST 01 01
- * length 5b 00
- * channel 1 00 01 00 00 00 64 00
- * radio type 00
- * channel 01
- * scan type 00
- * min scan time 00 00
- * max scan time 64 00
- * channel 2 00 02 00 00 00 64 00
- * channel 3 00 03 00 00 00 64 00
- * channel 4 00 04 00 00 00 64 00
- * channel 5 00 05 00 00 00 64 00
- * channel 6 00 06 00 00 00 64 00
- * channel 7 00 07 00 00 00 64 00
- * channel 8 00 08 00 00 00 64 00
- * channel 9 00 09 00 00 00 64 00
- * channel 10 00 0a 00 00 00 64 00
- * channel 11 00 0b 00 00 00 64 00
- * channel 12 00 0c 00 00 00 64 00
- * channel 13 00 0d 00 00 00 64 00
- *
- */
-static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
- struct chanscanparamset *chan_list,
- int chan_count)
-{
- size_t size = sizeof(struct chanscanparamset) *chan_count;
- struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv;
-
- chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
- memcpy(chan_tlv->chanscanparam, chan_list, size);
- chan_tlv->header.len = cpu_to_le16(size);
- return sizeof(chan_tlv->header) + size;
-}
-
-/*
- * Add RATES TLV of the form
- *
- * TLV-ID RATES 01 00
- * length 0e 00
- * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c
- *
- * The rates are in lbs_bg_rates[], but for the 802.11b
- * rates the high bit isn't set.
- */
-static int lbs_scan_add_rates_tlv(uint8_t *tlv)
-{
- int i;
- struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv;
-
- rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
- tlv += sizeof(rate_tlv->header);
- for (i = 0; i < MAX_RATES; i++) {
- *tlv = lbs_bg_rates[i];
- if (*tlv == 0)
- break;
- /* This code makes sure that the 802.11b rates (1 MBit/s, 2
- MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set.
- Note that the values are MBit/s * 2, to mark them as
- basic rates so that the firmware likes it better */
- if (*tlv == 0x02 || *tlv == 0x04 ||
- *tlv == 0x0b || *tlv == 0x16)
- *tlv |= 0x80;
- tlv++;
- }
- rate_tlv->header.len = cpu_to_le16(i);
- return sizeof(rate_tlv->header) + i;
-}
-
-/*
- * Generate the CMD_802_11_SCAN command with the proper tlv
- * for a bunch of channels.
- */
-static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
- struct chanscanparamset *chan_list, int chan_count)
-{
- int ret = -ENOMEM;
- struct cmd_ds_802_11_scan *scan_cmd;
- uint8_t *tlv; /* pointer into our current, growing TLV storage area */
-
- lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
- bsstype, chan_list ? chan_list[0].channumber : -1,
- chan_count);
-
- /* create the fixed part for scan command */
- scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
- if (scan_cmd == NULL)
- goto out;
-
- tlv = scan_cmd->tlvbuffer;
- /* TODO: do we need to scan for a specific BSSID?
- memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
- scan_cmd->bsstype = bsstype;
-
- /* add TLVs */
- if (priv->scan_ssid_len)
- tlv += lbs_scan_add_ssid_tlv(priv, tlv);
- if (chan_list && chan_count)
- tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
- tlv += lbs_scan_add_rates_tlv(tlv);
-
- /* This is the final data we are about to send */
- scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
- lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
- sizeof(*scan_cmd));
- lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
- tlv - scan_cmd->tlvbuffer);
-
- ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
- le16_to_cpu(scan_cmd->hdr.size),
- lbs_ret_80211_scan, 0);
-
-out:
- kfree(scan_cmd);
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Internal function used to start a scan based on an input config
- *
- * Use the input user scan configuration information when provided in
- * order to send the appropriate scan commands to firmware to populate or
- * update the internal driver scan table
- *
- * @param priv A pointer to struct lbs_private structure
- * @param full_scan Do a full-scan (blocking)
- *
- * @return 0 or < 0 if error
- */
-int lbs_scan_networks(struct lbs_private *priv, int full_scan)
-{
- int ret = -ENOMEM;
- struct chanscanparamset *chan_list;
- struct chanscanparamset *curr_chans;
- int chan_count;
- uint8_t bsstype = CMD_BSS_TYPE_ANY;
- int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
- union iwreq_data wrqu;
-#ifdef CONFIG_LIBERTAS_DEBUG
- struct bss_descriptor *iter;
- int i = 0;
- DECLARE_MAC_BUF(mac);
-#endif
-
- lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
-
- /* Cancel any partial outstanding partial scans if this scan
- * is a full scan.
- */
- if (full_scan && delayed_work_pending(&priv->scan_work))
- cancel_delayed_work(&priv->scan_work);
-
- /* User-specified bsstype or channel list
- TODO: this can be implemented if some user-space application
- need the feature. Formerly, it was accessible from debugfs,
- but then nowhere used.
- if (user_cfg) {
- if (user_cfg->bsstype)
- bsstype = user_cfg->bsstype;
- } */
-
- lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
-
- /* Create list of channels to scan */
- chan_list = kzalloc(sizeof(struct chanscanparamset) *
- LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
- if (!chan_list) {
- lbs_pr_alert("SCAN: chan_list empty\n");
- goto out;
- }
-
- /* We want to scan all channels */
- chan_count = lbs_scan_create_channel_list(priv, chan_list);
-
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
- if (priv->mesh_dev) {
- netif_stop_queue(priv->mesh_dev);
- netif_carrier_off(priv->mesh_dev);
- }
-
- /* Prepare to continue an interrupted scan */
- lbs_deb_scan("chan_count %d, scan_channel %d\n",
- chan_count, priv->scan_channel);
- curr_chans = chan_list;
- /* advance channel list by already-scanned-channels */
- if (priv->scan_channel > 0) {
- curr_chans += priv->scan_channel;
- chan_count -= priv->scan_channel;
- }
-
- /* Send scan command(s)
- * numchannels contains the number of channels we should maximally scan
- * chan_count is the total number of channels to scan
- */
-
- while (chan_count) {
- int to_scan = min(numchannels, chan_count);
- lbs_deb_scan("scanning %d of %d channels\n",
- to_scan, chan_count);
- ret = lbs_do_scan(priv, bsstype, curr_chans,
- to_scan);
- if (ret) {
- lbs_pr_err("SCAN_CMD failed\n");
- goto out2;
- }
- curr_chans += to_scan;
- chan_count -= to_scan;
-
- /* somehow schedule the next part of the scan */
- if (chan_count && !full_scan &&
- !priv->surpriseremoved) {
- /* -1 marks just that we're currently scanning */
- if (priv->scan_channel < 0)
- priv->scan_channel = to_scan;
- else
- priv->scan_channel += to_scan;
- cancel_delayed_work(&priv->scan_work);
- queue_delayed_work(priv->work_thread, &priv->scan_work,
- msecs_to_jiffies(300));
- /* skip over GIWSCAN event */
- goto out;
- }
-
- }
- memset(&wrqu, 0, sizeof(union iwreq_data));
- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
-
-#ifdef CONFIG_LIBERTAS_DEBUG
- /* Dump the scan table */
- mutex_lock(&priv->lock);
- lbs_deb_scan("scan table:\n");
- list_for_each_entry(iter, &priv->network_list, list)
- lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n",
- i++, print_mac(mac, iter->bssid), iter->rssi,
- escape_essid(iter->ssid, iter->ssid_len));
- mutex_unlock(&priv->lock);
-#endif
-
-out2:
- priv->scan_channel = 0;
-
-out:
- if (priv->connect_status == LBS_CONNECTED) {
- netif_carrier_on(priv->dev);
- if (!priv->tx_pending_len)
- netif_wake_queue(priv->dev);
- }
- if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) {
- netif_carrier_on(priv->mesh_dev);
- if (!priv->tx_pending_len)
- netif_wake_queue(priv->mesh_dev);
- }
- kfree(chan_list);
-
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
-}
-
-void lbs_scan_worker(struct work_struct *work)
-{
- struct lbs_private *priv =
- container_of(work, struct lbs_private, scan_work.work);
-
- lbs_deb_enter(LBS_DEB_SCAN);
- lbs_scan_networks(priv, 0);
- lbs_deb_leave(LBS_DEB_SCAN);
-}
-
-
-/*********************************************************************/
-/* */
-/* Result interpretation */
-/* */
-/*********************************************************************/
-
-/**
- * @brief Interpret a BSS scan response returned from the firmware
- *
- * Parse the various fixed fields and IEs passed back for a a BSS probe
- * response or beacon from the scan command. Record information as needed
- * in the scan table struct bss_descriptor for that entry.
- *
- * @param bss Output parameter: Pointer to the BSS Entry
- *
- * @return 0 or -1
- */
-static int lbs_process_bss(struct bss_descriptor *bss,
- uint8_t **pbeaconinfo, int *bytesleft)
-{
- struct ieeetypes_fhparamset *pFH;
- struct ieeetypes_dsparamset *pDS;
- struct ieeetypes_cfparamset *pCF;
- struct ieeetypes_ibssparamset *pibss;
- DECLARE_MAC_BUF(mac);
- struct ieeetypes_countryinfoset *pcountryinfo;
- uint8_t *pos, *end, *p;
- uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
- uint16_t beaconsize = 0;
- int ret;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- if (*bytesleft >= sizeof(beaconsize)) {
- /* Extract & convert beacon size from the command buffer */
- beaconsize = get_unaligned_le16(*pbeaconinfo);
- *bytesleft -= sizeof(beaconsize);
- *pbeaconinfo += sizeof(beaconsize);
- }
-
- if (beaconsize == 0 || beaconsize > *bytesleft) {
- *pbeaconinfo += *bytesleft;
- *bytesleft = 0;
- ret = -1;
- goto done;
- }
-
- /* Initialize the current working beacon pointer for this BSS iteration */
- pos = *pbeaconinfo;
- end = pos + beaconsize;
-
- /* Advance the return beacon pointer past the current beacon */
- *pbeaconinfo += beaconsize;
- *bytesleft -= beaconsize;
-
- memcpy(bss->bssid, pos, ETH_ALEN);
- lbs_deb_scan("process_bss: BSSID %s\n", print_mac(mac, bss->bssid));
- pos += ETH_ALEN;
-
- if ((end - pos) < 12) {
- lbs_deb_scan("process_bss: Not enough bytes left\n");
- ret = -1;
- goto done;
- }
-
- /*
- * next 4 fields are RSSI, time stamp, beacon interval,
- * and capability information
- */
-
- /* RSSI is 1 byte long */
- bss->rssi = *pos;
- lbs_deb_scan("process_bss: RSSI %d\n", *pos);
- pos++;
-
- /* time stamp is 8 bytes long */
- pos += 8;
-
- /* beacon interval is 2 bytes long */
- bss->beaconperiod = get_unaligned_le16(pos);
- pos += 2;
-
- /* capability information is 2 bytes long */
- bss->capability = get_unaligned_le16(pos);
- lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability);
- pos += 2;
-
- if (bss->capability & WLAN_CAPABILITY_PRIVACY)
- lbs_deb_scan("process_bss: WEP enabled\n");
- if (bss->capability & WLAN_CAPABILITY_IBSS)
- bss->mode = IW_MODE_ADHOC;
- else
- bss->mode = IW_MODE_INFRA;
-
- /* rest of the current buffer are IE's */
- lbs_deb_scan("process_bss: IE len %zd\n", end - pos);
- lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos);
-
- /* process variable IE */
- while (pos <= end - 2) {
- struct ieee80211_info_element * elem = (void *)pos;
-
- if (pos + elem->len > end) {
- lbs_deb_scan("process_bss: error in processing IE, "
- "bytes left < IE length\n");
- break;
- }
-
- switch (elem->id) {
- case MFIE_TYPE_SSID:
- bss->ssid_len = elem->len;
- memcpy(bss->ssid, elem->data, elem->len);
- lbs_deb_scan("got SSID IE: '%s', len %u\n",
- escape_essid(bss->ssid, bss->ssid_len),
- bss->ssid_len);
- break;
-
- case MFIE_TYPE_RATES:
- n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len);
- memcpy(bss->rates, elem->data, n_basic_rates);
- got_basic_rates = 1;
- lbs_deb_scan("got RATES IE\n");
- break;
-
- case MFIE_TYPE_FH_SET:
- pFH = (struct ieeetypes_fhparamset *) pos;
- memmove(&bss->phyparamset.fhparamset, pFH,
- sizeof(struct ieeetypes_fhparamset));
- lbs_deb_scan("got FH IE\n");
- break;
-
- case MFIE_TYPE_DS_SET:
- pDS = (struct ieeetypes_dsparamset *) pos;
- bss->channel = pDS->currentchan;
- memcpy(&bss->phyparamset.dsparamset, pDS,
- sizeof(struct ieeetypes_dsparamset));
- lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
- break;
-
- case MFIE_TYPE_CF_SET:
- pCF = (struct ieeetypes_cfparamset *) pos;
- memcpy(&bss->ssparamset.cfparamset, pCF,
- sizeof(struct ieeetypes_cfparamset));
- lbs_deb_scan("got CF IE\n");
- break;
-
- case MFIE_TYPE_IBSS_SET:
- pibss = (struct ieeetypes_ibssparamset *) pos;
- bss->atimwindow = le16_to_cpu(pibss->atimwindow);
- memmove(&bss->ssparamset.ibssparamset, pibss,
- sizeof(struct ieeetypes_ibssparamset));
- lbs_deb_scan("got IBSS IE\n");
- break;
-
- case MFIE_TYPE_COUNTRY:
- pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
- lbs_deb_scan("got COUNTRY IE\n");
- if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
- || pcountryinfo->len > 254) {
- lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n",
- pcountryinfo->len, sizeof(pcountryinfo->countrycode));
- ret = -1;
- goto done;
- }
-
- memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2);
- lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
- (uint8_t *) pcountryinfo,
- (int) (pcountryinfo->len + 2));
- break;
-
- case MFIE_TYPE_RATES_EX:
- /* only process extended supported rate if data rate is
- * already found. Data rate IE should come before
- * extended supported rate IE
- */
- lbs_deb_scan("got RATESEX IE\n");
- if (!got_basic_rates) {
- lbs_deb_scan("... but ignoring it\n");
- break;
- }
-
- n_ex_rates = elem->len;
- if (n_basic_rates + n_ex_rates > MAX_RATES)
- n_ex_rates = MAX_RATES - n_basic_rates;
-
- p = bss->rates + n_basic_rates;
- memcpy(p, elem->data, n_ex_rates);
- break;
-
- case MFIE_TYPE_GENERIC:
- if (elem->len >= 4 &&
- elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
- elem->data[2] == 0xf2 && elem->data[3] == 0x01) {
- bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
- memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
- lbs_deb_scan("got WPA IE\n");
- lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len);
- } else if (elem->len >= MARVELL_MESH_IE_LENGTH &&
- elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
- elem->data[2] == 0x43 && elem->data[3] == 0x04) {
- lbs_deb_scan("got mesh IE\n");
- bss->mesh = 1;
- } else {
- lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
- elem->data[0], elem->data[1],
- elem->data[2], elem->data[3],
- elem->len);
- }
- break;
-
- case MFIE_TYPE_RSN:
- lbs_deb_scan("got RSN IE\n");
- bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
- memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
- lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
- bss->rsn_ie, elem->len);
- break;
-
- default:
- lbs_deb_scan("got IE 0x%04x, len %d\n",
- elem->id, elem->len);
- break;
- }
-
- pos += elem->len + 2;
- }
-
- /* Timestamp */
- bss->last_scanned = jiffies;
- lbs_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));
-
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Send a scan command for all available channels filtered on a spec
- *
- * Used in association code and from debugfs
- *
- * @param priv A pointer to struct lbs_private structure
- * @param ssid A pointer to the SSID to scan for
- * @param ssid_len Length of the SSID
- *
- * @return 0-success, otherwise fail
- */
-int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
- uint8_t ssid_len)
-{
- int ret = 0;
-
- lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
- escape_essid(ssid, ssid_len));
-
- if (!ssid_len)
- goto out;
-
- memcpy(priv->scan_ssid, ssid, ssid_len);
- priv->scan_ssid_len = ssid_len;
-
- lbs_scan_networks(priv, 1);
- if (priv->surpriseremoved) {
- ret = -1;
- goto out;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
-}
-
-
-
-
-/*********************************************************************/
-/* */
-/* Support for Wireless Extensions */
-/* */
-/*********************************************************************/
-
-
-#define MAX_CUSTOM_LEN 64
-
-static inline char *lbs_translate_scan(struct lbs_private *priv,
- char *start, char *stop,
- struct bss_descriptor *bss)
-{
- struct chan_freq_power *cfp;
- char *current_val; /* For rates */
- struct iw_event iwe; /* Temporary buffer */
- int j;
-#define PERFECT_RSSI ((uint8_t)50)
-#define WORST_RSSI ((uint8_t)0)
-#define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI))
- uint8_t rssi;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- cfp = lbs_find_cfp_by_band_and_channel(priv, 0, bss->channel);
- if (!cfp) {
- lbs_deb_scan("Invalid channel number %d\n", bss->channel);
- start = NULL;
- goto out;
- }
-
- /* First entry *MUST* be the BSSID */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
-
- /* SSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
- start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
-
- /* Mode */
- iwe.cmd = SIOCGIWMODE;
- iwe.u.mode = bss->mode;
- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
-
- /* Frequency */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = (long)cfp->freq * 100000;
- iwe.u.freq.e = 1;
- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
- iwe.u.qual.level = SCAN_RSSI(bss->rssi);
-
- rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
- iwe.u.qual.qual =
- (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
- (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
- (RSSI_DIFF * RSSI_DIFF);
- if (iwe.u.qual.qual > 100)
- iwe.u.qual.qual = 100;
-
- if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
- iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
- } else {
- iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
- }
-
- /* Locally created ad-hoc BSSs won't have beacons if this is the
- * only station in the adhoc network; so get signal strength
- * from receive statistics.
- */
- if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate
- && !lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
- bss->ssid, bss->ssid_len)) {
- int snr, nf;
- snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
- nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
- iwe.u.qual.level = CAL_RSSI(snr, nf);
- }
- start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (bss->capability & WLAN_CAPABILITY_PRIVACY) {
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- } else {
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- }
- iwe.u.data.length = 0;
- start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
-
- current_val = start + IW_EV_LCP_LEN;
-
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = 0;
- iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = 0;
-
- for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
- /* Bit rate given in 500 kb/s units */
- iwe.u.bitrate.value = bss->rates[j] * 500000;
- current_val = iwe_stream_add_value(start, current_val,
- stop, &iwe, IW_EV_PARAM_LEN);
- }
- if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
- && !lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
- bss->ssid, bss->ssid_len)) {
- iwe.u.bitrate.value = 22 * 500000;
- current_val = iwe_stream_add_value(start, current_val,
- stop, &iwe, IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if((current_val - start) > IW_EV_LCP_LEN)
- start = current_val;
-
- memset(&iwe, 0, sizeof(iwe));
- if (bss->wpa_ie_len) {
- char buf[MAX_WPA_IE_LEN];
- memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = bss->wpa_ie_len;
- start = iwe_stream_add_point(start, stop, &iwe, buf);
- }
-
- memset(&iwe, 0, sizeof(iwe));
- if (bss->rsn_ie_len) {
- char buf[MAX_WPA_IE_LEN];
- memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = bss->rsn_ie_len;
- start = iwe_stream_add_point(start, stop, &iwe, buf);
- }
-
- if (bss->mesh) {
- char custom[MAX_CUSTOM_LEN];
- char *p = custom;
-
- iwe.cmd = IWEVCUSTOM;
- p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
- iwe.u.data.length = p - custom;
- if (iwe.u.data.length)
- start = iwe_stream_add_point(start, stop, &iwe, custom);
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_SCAN, "start %p", start);
- return start;
-}
-
-
-/**
- * @brief Handle Scan Network ioctl
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param vwrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- *
- * @return 0 --success, otherwise fail
- */
-int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (!netif_running(dev)) {
- ret = -ENETDOWN;
- goto out;
- }
-
- /* mac80211 does this:
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->type != IEEE80211_IF_TYPE_xxx) {
- ret = -EOPNOTSUPP;
- goto out;
- }
- */
-
- if (wrqu->data.length == sizeof(struct iw_scan_req) &&
- wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
- priv->scan_ssid_len = req->essid_len;
- memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
- lbs_deb_wext("set_scan, essid '%s'\n",
- escape_essid(priv->scan_ssid, priv->scan_ssid_len));
- } else {
- priv->scan_ssid_len = 0;
- }
-
- if (!delayed_work_pending(&priv->scan_work))
- queue_delayed_work(priv->work_thread, &priv->scan_work,
- msecs_to_jiffies(50));
- /* set marker that currently a scan is taking place */
- priv->scan_channel = -1;
-
- if (priv->surpriseremoved)
- ret = -EIO;
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-
-/**
- * @brief Handle Retrieve scan table ioctl
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param dwrq A pointer to iw_point structure
- * @param extra A pointer to extra data buf
- *
- * @return 0 --success, otherwise fail
- */
-int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
-#define SCAN_ITEM_SIZE 128
- struct lbs_private *priv = dev->priv;
- int err = 0;
- char *ev = extra;
- char *stop = ev + dwrq->length;
- struct bss_descriptor *iter_bss;
- struct bss_descriptor *safe;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* iwlist should wait until the current scan is finished */
- if (priv->scan_channel)
- return -EAGAIN;
-
- /* Update RSSI if current BSS is a locally created ad-hoc BSS */
- if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- CMD_OPTION_WAITFORRSP, 0, NULL);
-
- mutex_lock(&priv->lock);
- list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
- char *next_ev;
- unsigned long stale_time;
-
- if (stop - ev < SCAN_ITEM_SIZE) {
- err = -E2BIG;
- break;
- }
-
- /* For mesh device, list only mesh networks */
- if (dev == priv->mesh_dev && !iter_bss->mesh)
- continue;
-
- /* Prune old an old scan result */
- stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
- if (time_after(jiffies, stale_time)) {
- list_move_tail(&iter_bss->list, &priv->network_free_list);
- clear_bss_descriptor(iter_bss);
- continue;
- }
-
- /* Translate to WE format this entry */
- next_ev = lbs_translate_scan(priv, ev, stop, iter_bss);
- if (next_ev == NULL)
- continue;
- ev = next_ev;
- }
- mutex_unlock(&priv->lock);
-
- dwrq->length = (ev - extra);
- dwrq->flags = 0;
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
- return err;
-}
-
-
-
-
-/*********************************************************************/
-/* */
-/* Command execution */
-/* */
-/*********************************************************************/
-
-
-/**
- * @brief This function handles the command response of scan
- *
- * Called from handle_cmd_response() in cmdrespc.
- *
- * The response buffer for the scan command has the following
- * memory layout:
- *
- * .-----------------------------------------------------------.
- * | header (4 * sizeof(u16)): Standard command response hdr |
- * .-----------------------------------------------------------.
- * | bufsize (u16) : sizeof the BSS Description data |
- * .-----------------------------------------------------------.
- * | NumOfSet (u8) : Number of BSS Descs returned |
- * .-----------------------------------------------------------.
- * | BSSDescription data (variable, size given in bufsize) |
- * .-----------------------------------------------------------.
- * | TLV data (variable, size calculated using header->size, |
- * | bufsize and sizeof the fixed fields above) |
- * .-----------------------------------------------------------.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param resp A pointer to cmd_ds_command
- *
- * @return 0 or -1
- */
-static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
- struct cmd_header *resp)
-{
- struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
- struct bss_descriptor *iter_bss;
- struct bss_descriptor *safe;
- uint8_t *bssinfo;
- uint16_t scanrespsize;
- int bytesleft;
- int idx;
- int tlvbufsize;
- int ret;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- /* Prune old entries from scan table */
- list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
- unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
- if (time_before(jiffies, stale_time))
- continue;
- list_move_tail (&iter_bss->list, &priv->network_free_list);
- clear_bss_descriptor(iter_bss);
- }
-
- if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
- lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
- scanresp->nr_sets, MAX_NETWORK_COUNT);
- ret = -1;
- goto done;
- }
-
- bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
- lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
-
- scanrespsize = le16_to_cpu(resp->size);
- lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
-
- bssinfo = scanresp->bssdesc_and_tlvbuffer;
-
- /* The size of the TLV buffer is equal to the entire command response
- * size (scanrespsize) minus the fixed fields (sizeof()'s), the
- * BSS Descriptions (bssdescriptsize as bytesLef) and the command
- * response header (S_DS_GEN)
- */
- tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
- + sizeof(scanresp->nr_sets)
- + S_DS_GEN);
-
- /*
- * Process each scan response returned (scanresp->nr_sets). Save
- * the information in the newbssentry and then insert into the
- * driver scan table either as an update to an existing entry
- * or as an addition at the end of the table
- */
- for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
- struct bss_descriptor new;
- struct bss_descriptor *found = NULL;
- struct bss_descriptor *oldest = NULL;
- DECLARE_MAC_BUF(mac);
-
- /* Process the data fields and IEs returned for this BSS */
- memset(&new, 0, sizeof (struct bss_descriptor));
- if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
- /* error parsing the scan response, skipped */
- lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
- continue;
- }
-
- /* Try to find this bss in the scan table */
- list_for_each_entry (iter_bss, &priv->network_list, list) {
- if (is_same_network(iter_bss, &new)) {
- found = iter_bss;
- break;
- }
-
- if ((oldest == NULL) ||
- (iter_bss->last_scanned < oldest->last_scanned))
- oldest = iter_bss;
- }
-
- if (found) {
- /* found, clear it */
- clear_bss_descriptor(found);
- } else if (!list_empty(&priv->network_free_list)) {
- /* Pull one from the free list */
- found = list_entry(priv->network_free_list.next,
- struct bss_descriptor, list);
- list_move_tail(&found->list, &priv->network_list);
- } else if (oldest) {
- /* If there are no more slots, expire the oldest */
- found = oldest;
- clear_bss_descriptor(found);
- list_move_tail(&found->list, &priv->network_list);
- } else {
- continue;
- }
-
- lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid));
-
- /* Copy the locally created newbssentry to the scan table */
- memcpy(found, &new, offsetof(struct bss_descriptor, list));
- }
-
- ret = 0;
-
-done:
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
-}
+++ /dev/null
-/**
- * Interface for the wlan network scan routines
- *
- * Driver interface functions and type declarations for the scan module
- * implemented in scan.c.
- */
-#ifndef _LBS_SCAN_H
-#define _LBS_SCAN_H
-
-/**
- * @brief Maximum number of channels that can be sent in a setuserscan ioctl
- */
-#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
-
-int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
-
-int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
- u8 ssid_len);
-
-int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra);
-int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-int lbs_scan_networks(struct lbs_private *priv, int full_scan);
-
-void lbs_scan_worker(struct work_struct *work);
-
-#endif
+++ /dev/null
-/**
- * This file contains the handling of TX in wlan driver.
- */
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include "hostcmd.h"
-#include "radiotap.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "wext.h"
-
-/**
- * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
- * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1)
- *
- * @param rate Input rate
- * @return Output Rate (0 if invalid)
- */
-static u32 convert_radiotap_rate_to_mv(u8 rate)
-{
- switch (rate) {
- case 2: /* 1 Mbps */
- return 0 | (1 << 4);
- case 4: /* 2 Mbps */
- return 1 | (1 << 4);
- case 11: /* 5.5 Mbps */
- return 2 | (1 << 4);
- case 22: /* 11 Mbps */
- return 3 | (1 << 4);
- case 12: /* 6 Mbps */
- return 4 | (1 << 4);
- case 18: /* 9 Mbps */
- return 5 | (1 << 4);
- case 24: /* 12 Mbps */
- return 6 | (1 << 4);
- case 36: /* 18 Mbps */
- return 7 | (1 << 4);
- case 48: /* 24 Mbps */
- return 8 | (1 << 4);
- case 72: /* 36 Mbps */
- return 9 | (1 << 4);
- case 96: /* 48 Mbps */
- return 10 | (1 << 4);
- case 108: /* 54 Mbps */
- return 11 | (1 << 4);
- }
- return 0;
-}
-
-/**
- * @brief This function checks the conditions and sends packet to IF
- * layer if everything is ok.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param skb A pointer to skb which includes TX packet
- * @return 0 or -1
- */
-int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- unsigned long flags;
- struct lbs_private *priv = dev->priv;
- struct txpd *txpd;
- char *p802x_hdr;
- uint16_t pkt_len;
- int ret;
-
- lbs_deb_enter(LBS_DEB_TX);
-
- ret = NETDEV_TX_OK;
-
- /* We need to protect against the queues being restarted before
- we get round to stopping them */
- spin_lock_irqsave(&priv->driver_lock, flags);
-
- if (priv->surpriseremoved)
- goto free;
-
- if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
- lbs_deb_tx("tx err: skb length %d 0 or > %zd\n",
- skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
- /* We'll never manage to send this one; drop it and return 'OK' */
-
- priv->stats.tx_dropped++;
- priv->stats.tx_errors++;
- goto free;
- }
-
-
- netif_stop_queue(priv->dev);
- if (priv->mesh_dev)
- netif_stop_queue(priv->mesh_dev);
-
- if (priv->tx_pending_len) {
- /* This can happen if packets come in on the mesh and eth
- device simultaneously -- there's no mutual exclusion on
- hard_start_xmit() calls between devices. */
- lbs_deb_tx("Packet on %s while busy\n", dev->name);
- ret = NETDEV_TX_BUSY;
- goto unlock;
- }
-
- priv->tx_pending_len = -1;
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
-
- txpd = (void *)priv->tx_pending_buf;
- memset(txpd, 0, sizeof(struct txpd));
-
- p802x_hdr = skb->data;
- pkt_len = skb->len;
-
- if (dev == priv->rtap_net_dev) {
- struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
-
- /* set txpd fields from the radiotap header */
- txpd->tx_control = cpu_to_le32(convert_radiotap_rate_to_mv(rtap_hdr->rate));
-
- /* skip the radiotap header */
- p802x_hdr += sizeof(*rtap_hdr);
- pkt_len -= sizeof(*rtap_hdr);
-
- /* copy destination address from 802.11 header */
- memcpy(txpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
- } else {
- /* copy destination address from 802.3 header */
- memcpy(txpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
- }
-
- txpd->tx_packet_length = cpu_to_le16(pkt_len);
- txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
-
- if (dev == priv->mesh_dev)
- txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
-
- lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
-
- lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
-
- memcpy(&txpd[1], p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- priv->tx_pending_len = pkt_len + sizeof(struct txpd);
-
- lbs_deb_tx("%s lined up packet\n", __func__);
-
- priv->stats.tx_packets++;
- priv->stats.tx_bytes += skb->len;
-
- dev->trans_start = jiffies;
-
- if (priv->monitormode) {
- /* Keep the skb to echo it back once Tx feedback is
- received from FW */
- skb_orphan(skb);
-
- /* Keep the skb around for when we get feedback */
- priv->currenttxskb = skb;
- } else {
- free:
- dev_kfree_skb_any(skb);
- }
- unlock:
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- wake_up(&priv->waitq);
-
- lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function sends to the host the last transmitted packet,
- * filling the radiotap headers with transmission information.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param status A 32 bit value containing transmission status.
- *
- * @returns void
- */
-void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
-{
- struct tx_radiotap_hdr *radiotap_hdr;
-
- if (!priv->monitormode || priv->currenttxskb == NULL)
- return;
-
- radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
-
- radiotap_hdr->data_retries = try_count ?
- (1 + priv->txretrycount - try_count) : 0;
-
- priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
- priv->rtap_net_dev);
- netif_rx(priv->currenttxskb);
-
- priv->currenttxskb = NULL;
-
- if (priv->connect_status == LBS_CONNECTED)
- netif_wake_queue(priv->dev);
-
- if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED))
- netif_wake_queue(priv->mesh_dev);
-}
-EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
+++ /dev/null
-/**
- * This header file contains definition for global types
- */
-#ifndef _LBS_TYPES_H_
-#define _LBS_TYPES_H_
-
-#include <linux/if_ether.h>
-#include <asm/byteorder.h>
-
-struct ieeetypes_cfparamset {
- u8 elementid;
- u8 len;
- u8 cfpcnt;
- u8 cfpperiod;
- __le16 cfpmaxduration;
- __le16 cfpdurationremaining;
-} __attribute__ ((packed));
-
-
-struct ieeetypes_ibssparamset {
- u8 elementid;
- u8 len;
- __le16 atimwindow;
-} __attribute__ ((packed));
-
-union IEEEtypes_ssparamset {
- struct ieeetypes_cfparamset cfparamset;
- struct ieeetypes_ibssparamset ibssparamset;
-} __attribute__ ((packed));
-
-struct ieeetypes_fhparamset {
- u8 elementid;
- u8 len;
- __le16 dwelltime;
- u8 hopset;
- u8 hoppattern;
- u8 hopindex;
-} __attribute__ ((packed));
-
-struct ieeetypes_dsparamset {
- u8 elementid;
- u8 len;
- u8 currentchan;
-} __attribute__ ((packed));
-
-union ieeetypes_phyparamset {
- struct ieeetypes_fhparamset fhparamset;
- struct ieeetypes_dsparamset dsparamset;
-} __attribute__ ((packed));
-
-struct ieeetypes_assocrsp {
- __le16 capability;
- __le16 statuscode;
- __le16 aid;
- u8 iebuffer[1];
-} __attribute__ ((packed));
-
-/** TLV type ID definition */
-#define PROPRIETARY_TLV_BASE_ID 0x0100
-
-/* Terminating TLV type */
-#define MRVL_TERMINATE_TLV_ID 0xffff
-
-#define TLV_TYPE_SSID 0x0000
-#define TLV_TYPE_RATES 0x0001
-#define TLV_TYPE_PHY_FH 0x0002
-#define TLV_TYPE_PHY_DS 0x0003
-#define TLV_TYPE_CF 0x0004
-#define TLV_TYPE_IBSS 0x0006
-
-#define TLV_TYPE_DOMAIN 0x0007
-
-#define TLV_TYPE_POWER_CAPABILITY 0x0021
-
-#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0)
-#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1)
-#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2)
-#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4)
-#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5)
-#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6)
-#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7)
-#define TLV_TYPE_LED_GPIO (PROPRIETARY_TLV_BASE_ID + 8)
-#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9)
-#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10)
-#define TLV_TYPE_REASSOCAP (PROPRIETARY_TLV_BASE_ID + 11)
-#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12)
-#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13)
-#define TLV_TYPE_BCASTPROBE (PROPRIETARY_TLV_BASE_ID + 14)
-#define TLV_TYPE_NUMSSID_PROBE (PROPRIETARY_TLV_BASE_ID + 15)
-#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16)
-#define TLV_TYPE_CRYPTO_DATA (PROPRIETARY_TLV_BASE_ID + 17)
-#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18)
-#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19)
-#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
-#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23)
-
-/** TLV related data structures*/
-struct mrvlietypesheader {
- __le16 type;
- __le16 len;
-} __attribute__ ((packed));
-
-struct mrvlietypes_data {
- struct mrvlietypesheader header;
- u8 Data[1];
-} __attribute__ ((packed));
-
-struct mrvlietypes_ratesparamset {
- struct mrvlietypesheader header;
- u8 rates[1];
-} __attribute__ ((packed));
-
-struct mrvlietypes_ssidparamset {
- struct mrvlietypesheader header;
- u8 ssid[1];
-} __attribute__ ((packed));
-
-struct mrvlietypes_wildcardssidparamset {
- struct mrvlietypesheader header;
- u8 MaxSsidlength;
- u8 ssid[1];
-} __attribute__ ((packed));
-
-struct chanscanmode {
-#ifdef __BIG_ENDIAN_BITFIELD
- u8 reserved_2_7:6;
- u8 disablechanfilt:1;
- u8 passivescan:1;
-#else
- u8 passivescan:1;
- u8 disablechanfilt:1;
- u8 reserved_2_7:6;
-#endif
-} __attribute__ ((packed));
-
-struct chanscanparamset {
- u8 radiotype;
- u8 channumber;
- struct chanscanmode chanscanmode;
- __le16 minscantime;
- __le16 maxscantime;
-} __attribute__ ((packed));
-
-struct mrvlietypes_chanlistparamset {
- struct mrvlietypesheader header;
- struct chanscanparamset chanscanparam[1];
-} __attribute__ ((packed));
-
-struct cfparamset {
- u8 cfpcnt;
- u8 cfpperiod;
- __le16 cfpmaxduration;
- __le16 cfpdurationremaining;
-} __attribute__ ((packed));
-
-struct ibssparamset {
- __le16 atimwindow;
-} __attribute__ ((packed));
-
-struct mrvlietypes_ssparamset {
- struct mrvlietypesheader header;
- union {
- struct cfparamset cfparamset[1];
- struct ibssparamset ibssparamset[1];
- } cf_ibss;
-} __attribute__ ((packed));
-
-struct fhparamset {
- __le16 dwelltime;
- u8 hopset;
- u8 hoppattern;
- u8 hopindex;
-} __attribute__ ((packed));
-
-struct dsparamset {
- u8 currentchan;
-} __attribute__ ((packed));
-
-struct mrvlietypes_phyparamset {
- struct mrvlietypesheader header;
- union {
- struct fhparamset fhparamset[1];
- struct dsparamset dsparamset[1];
- } fh_ds;
-} __attribute__ ((packed));
-
-struct mrvlietypes_rsnparamset {
- struct mrvlietypesheader header;
- u8 rsnie[1];
-} __attribute__ ((packed));
-
-struct mrvlietypes_tsftimestamp {
- struct mrvlietypesheader header;
- __le64 tsftable[1];
-} __attribute__ ((packed));
-
-/** Local Power capability */
-struct mrvlietypes_powercapability {
- struct mrvlietypesheader header;
- s8 minpower;
- s8 maxpower;
-} __attribute__ ((packed));
-
-/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
-struct mrvlietypes_thresholds {
- struct mrvlietypesheader header;
- u8 value;
- u8 freq;
-} __attribute__ ((packed));
-
-struct mrvlietypes_beaconsmissed {
- struct mrvlietypesheader header;
- u8 beaconmissed;
- u8 reserved;
-} __attribute__ ((packed));
-
-struct mrvlietypes_numprobes {
- struct mrvlietypesheader header;
- __le16 numprobes;
-} __attribute__ ((packed));
-
-struct mrvlietypes_bcastprobe {
- struct mrvlietypesheader header;
- __le16 bcastprobe;
-} __attribute__ ((packed));
-
-struct mrvlietypes_numssidprobe {
- struct mrvlietypesheader header;
- __le16 numssidprobe;
-} __attribute__ ((packed));
-
-struct led_pin {
- u8 led;
- u8 pin;
-} __attribute__ ((packed));
-
-struct mrvlietypes_ledgpio {
- struct mrvlietypesheader header;
- struct led_pin ledpin[1];
-} __attribute__ ((packed));
-
-struct led_bhv {
- uint8_t firmwarestate;
- uint8_t led;
- uint8_t ledstate;
- uint8_t ledarg;
-} __attribute__ ((packed));
-
-
-struct mrvlietypes_ledbhv {
- struct mrvlietypesheader header;
- struct led_bhv ledbhv[1];
-} __attribute__ ((packed));
-
-#endif
+++ /dev/null
-/**
- * This file contains ioctl functions
- */
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <linux/bitops.h>
-
-#include <net/ieee80211.h>
-#include <net/iw_handler.h>
-
-#include "host.h"
-#include "radiotap.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "wext.h"
-#include "scan.h"
-#include "assoc.h"
-#include "cmd.h"
-#include "ioctl.h"
-
-static inline void lbs_postpone_association_work(struct lbs_private *priv)
-{
- if (priv->surpriseremoved)
- return;
- cancel_delayed_work(&priv->assoc_work);
- queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
-}
-
-static inline void lbs_cancel_association_work(struct lbs_private *priv)
-{
- cancel_delayed_work(&priv->assoc_work);
- kfree(priv->pending_assoc_req);
- priv->pending_assoc_req = NULL;
-}
-
-
-/**
- * @brief Find the channel frequency power info with specific channel
- *
- * @param priv A pointer to struct lbs_private structure
- * @param band it can be BAND_A, BAND_G or BAND_B
- * @param channel the channel for looking
- * @return A pointer to struct chan_freq_power structure or NULL if not find.
- */
-struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
- struct lbs_private *priv,
- u8 band,
- u16 channel)
-{
- struct chan_freq_power *cfp = NULL;
- struct region_channel *rc;
- int i, j;
-
- for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
- rc = &priv->region_channel[j];
-
- if (priv->enable11d)
- rc = &priv->universal_channel[j];
- if (!rc->valid || !rc->CFP)
- continue;
- if (rc->band != band)
- continue;
- for (i = 0; i < rc->nrcfp; i++) {
- if (rc->CFP[i].channel == channel) {
- cfp = &rc->CFP[i];
- break;
- }
- }
- }
-
- if (!cfp && channel)
- lbs_deb_wext("lbs_find_cfp_by_band_and_channel: can't find "
- "cfp by band %d / channel %d\n", band, channel);
-
- return cfp;
-}
-
-/**
- * @brief Find the channel frequency power info with specific frequency
- *
- * @param priv A pointer to struct lbs_private structure
- * @param band it can be BAND_A, BAND_G or BAND_B
- * @param freq the frequency for looking
- * @return A pointer to struct chan_freq_power structure or NULL if not find.
- */
-static struct chan_freq_power *find_cfp_by_band_and_freq(
- struct lbs_private *priv,
- u8 band,
- u32 freq)
-{
- struct chan_freq_power *cfp = NULL;
- struct region_channel *rc;
- int i, j;
-
- for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
- rc = &priv->region_channel[j];
-
- if (priv->enable11d)
- rc = &priv->universal_channel[j];
- if (!rc->valid || !rc->CFP)
- continue;
- if (rc->band != band)
- continue;
- for (i = 0; i < rc->nrcfp; i++) {
- if (rc->CFP[i].freq == freq) {
- cfp = &rc->CFP[i];
- break;
- }
- }
- }
-
- if (!cfp && freq)
- lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by "
- "band %d / freq %d\n", band, freq);
-
- return cfp;
-}
-
-
-/**
- * @brief Set Radio On/OFF
- *
- * @param priv A pointer to struct lbs_private structure
- * @option Radio Option
- * @return 0 --success, otherwise fail
- */
-static int lbs_radio_ioctl(struct lbs_private *priv, u8 option)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (priv->radioon != option) {
- lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
- priv->radioon = option;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_RADIO_CONTROL,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
- }
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Copy active data rates based on adapter mode and status
- *
- * @param priv A pointer to struct lbs_private structure
- * @param rate The buf to return the active rates
- */
-static void copy_active_data_rates(struct lbs_private *priv, u8 *rates)
-{
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if ((priv->connect_status != LBS_CONNECTED) &&
- (priv->mesh_connect_status != LBS_CONNECTED))
- memcpy(rates, lbs_bg_rates, MAX_RATES);
- else
- memcpy(rates, priv->curbssparams.rates, MAX_RATES);
-
- lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
- char *cwrq, char *extra)
-{
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* We could add support for 802.11n here as needed. Jean II */
- snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
- struct iw_freq *fwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- struct chan_freq_power *cfp;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
- priv->curbssparams.channel);
-
- if (!cfp) {
- if (priv->curbssparams.channel)
- lbs_deb_wext("invalid channel %d\n",
- priv->curbssparams.channel);
- return -EINVAL;
- }
-
- fwrq->m = (long)cfp->freq * 100000;
- fwrq->e = 1;
-
- lbs_deb_wext("freq %u\n", fwrq->m);
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
- struct sockaddr *awrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (priv->connect_status == LBS_CONNECTED) {
- memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
- } else {
- memset(awrq->sa_data, 0, ETH_ALEN);
- }
- awrq->sa_family = ARPHRD_ETHER;
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /*
- * Check the size of the string
- */
-
- if (dwrq->length > 16) {
- return -E2BIG;
- }
-
- mutex_lock(&priv->lock);
- memset(priv->nodename, 0, sizeof(priv->nodename));
- memcpy(priv->nodename, extra, dwrq->length);
- mutex_unlock(&priv->lock);
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- dwrq->length = strlen(priv->nodename);
- memcpy(extra, priv->nodename, dwrq->length);
- extra[dwrq->length] = '\0';
-
- dwrq->flags = 1; /* active */
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* Use nickname to indicate that mesh is on */
-
- if (priv->mesh_connect_status == LBS_CONNECTED) {
- strncpy(extra, "Mesh", 12);
- extra[12] = '\0';
- dwrq->length = strlen(extra);
- }
-
- else {
- extra[0] = '\0';
- dwrq->length = 0;
- }
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
- u32 rthr = vwrq->value;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (vwrq->disabled) {
- priv->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
- } else {
- if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE)
- return -EINVAL;
- priv->rtsthsd = rthr;
- }
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
- OID_802_11_RTS_THRESHOLD, &rthr);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- priv->rtsthsd = 0;
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
- OID_802_11_RTS_THRESHOLD, NULL);
- if (ret)
- goto out;
-
- vwrq->value = priv->rtsthsd;
- vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
- || (vwrq->value > MRVDRV_RTS_MAX_VALUE));
- vwrq->fixed = 1;
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- int ret = 0;
- u32 fthr = vwrq->value;
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (vwrq->disabled) {
- priv->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
- } else {
- if (fthr < MRVDRV_FRAG_MIN_VALUE
- || fthr > MRVDRV_FRAG_MAX_VALUE)
- return -EINVAL;
- priv->fragthsd = fthr;
- }
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
- OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- priv->fragthsd = 0;
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_SNMP_MIB,
- CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
- OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
- if (ret)
- goto out;
-
- vwrq->value = priv->fragthsd;
- vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
- || (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
- vwrq->fixed = 1;
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_mode(struct net_device *dev,
- struct iw_request_info *info, u32 * uwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- *uwrq = priv->mode;
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int mesh_wlan_get_mode(struct net_device *dev,
- struct iw_request_info *info, u32 * uwrq,
- char *extra)
-{
- lbs_deb_enter(LBS_DEB_WEXT);
-
- *uwrq = IW_MODE_REPEAT ;
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_get_txpow(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_RF_TX_POWER,
- CMD_ACT_TX_POWER_OPT_GET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
-
- if (ret)
- goto out;
-
- lbs_deb_wext("tx power level %d dbm\n", priv->txpowerlevel);
- vwrq->value = priv->txpowerlevel;
- vwrq->fixed = 1;
- if (priv->radioon) {
- vwrq->disabled = 0;
- vwrq->flags = IW_TXPOW_DBM;
- } else {
- vwrq->disabled = 1;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (vwrq->flags == IW_RETRY_LIMIT) {
- /* The MAC has a 4-bit Total_Tx_Count register
- Total_Tx_Count = 1 + Tx_Retry_Count */
-#define TX_RETRY_MIN 0
-#define TX_RETRY_MAX 14
- if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
- return -EINVAL;
-
- /* Adding 1 to convert retry count to try count */
- priv->txretrycount = vwrq->value + 1;
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP,
- OID_802_11_TX_RETRYCOUNT, NULL);
-
- if (ret)
- goto out;
- } else {
- return -EOPNOTSUPP;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- priv->txretrycount = 0;
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_SNMP_MIB,
- CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
- OID_802_11_TX_RETRYCOUNT, NULL);
- if (ret)
- goto out;
-
- vwrq->disabled = 0;
- if (!vwrq->flags) {
- vwrq->flags = IW_RETRY_LIMIT;
- /* Subtract 1 to convert try count to retry count */
- vwrq->value = priv->txretrycount - 1;
- }
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static inline void sort_channels(struct iw_freq *freq, int num)
-{
- int i, j;
- struct iw_freq temp;
-
- for (i = 0; i < num; i++)
- for (j = i + 1; j < num; j++)
- if (freq[i].i > freq[j].i) {
- temp.i = freq[i].i;
- temp.m = freq[i].m;
-
- freq[i].i = freq[j].i;
- freq[i].m = freq[j].m;
-
- freq[j].i = temp.i;
- freq[j].m = temp.m;
- }
-}
-
-/* data rate listing
- MULTI_BANDS:
- abg a b b/g
- Infra G(12) A(8) B(4) G(12)
- Adhoc A+B(12) A(8) B(4) B(4)
-
- non-MULTI_BANDS:
- b b/g
- Infra B(4) G(12)
- Adhoc B(4) B(4)
- */
-/**
- * @brief Get Range Info
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param vwrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- * @return 0 --success, otherwise fail
- */
-static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- int i, j;
- struct lbs_private *priv = dev->priv;
- struct iw_range *range = (struct iw_range *)extra;
- struct chan_freq_power *cfp;
- u8 rates[MAX_RATES + 1];
-
- u8 flag = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- dwrq->length = sizeof(struct iw_range);
- memset(range, 0, sizeof(struct iw_range));
-
- range->min_nwid = 0;
- range->max_nwid = 0;
-
- memset(rates, 0, sizeof(rates));
- copy_active_data_rates(priv, rates);
- range->num_bitrates = strnlen(rates, IW_MAX_BITRATES);
- for (i = 0; i < range->num_bitrates; i++)
- range->bitrate[i] = rates[i] * 500000;
- range->num_bitrates = i;
- lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
- range->num_bitrates);
-
- range->num_frequency = 0;
-
- range->scan_capa = IW_SCAN_CAPA_ESSID;
-
- if (priv->enable11d &&
- (priv->connect_status == LBS_CONNECTED ||
- priv->mesh_connect_status == LBS_CONNECTED)) {
- u8 chan_no;
- u8 band;
-
- struct parsed_region_chan_11d *parsed_region_chan =
- &priv->parsed_region_chan;
-
- if (parsed_region_chan == NULL) {
- lbs_deb_wext("11d: parsed_region_chan is NULL\n");
- goto out;
- }
- band = parsed_region_chan->band;
- lbs_deb_wext("band %d, nr_char %d\n", band,
- parsed_region_chan->nr_chan);
-
- for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
- && (i < parsed_region_chan->nr_chan); i++) {
- chan_no = parsed_region_chan->chanpwr[i].chan;
- lbs_deb_wext("chan_no %d\n", chan_no);
- range->freq[range->num_frequency].i = (long)chan_no;
- range->freq[range->num_frequency].m =
- (long)lbs_chan_2_freq(chan_no) * 100000;
- range->freq[range->num_frequency].e = 1;
- range->num_frequency++;
- }
- flag = 1;
- }
- if (!flag) {
- for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
- && (j < ARRAY_SIZE(priv->region_channel)); j++) {
- cfp = priv->region_channel[j].CFP;
- for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
- && priv->region_channel[j].valid
- && cfp
- && (i < priv->region_channel[j].nrcfp); i++) {
- range->freq[range->num_frequency].i =
- (long)cfp->channel;
- range->freq[range->num_frequency].m =
- (long)cfp->freq * 100000;
- range->freq[range->num_frequency].e = 1;
- cfp++;
- range->num_frequency++;
- }
- }
- }
-
- lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
- IW_MAX_FREQUENCIES, range->num_frequency);
-
- range->num_channels = range->num_frequency;
-
- sort_channels(&range->freq[0], range->num_frequency);
-
- /*
- * Set an indication of the max TCP throughput in bit/s that we can
- * expect using this interface
- */
- if (i > 2)
- range->throughput = 5000 * 1000;
- else
- range->throughput = 1500 * 1000;
-
- range->min_rts = MRVDRV_RTS_MIN_VALUE;
- range->max_rts = MRVDRV_RTS_MAX_VALUE;
- range->min_frag = MRVDRV_FRAG_MIN_VALUE;
- range->max_frag = MRVDRV_FRAG_MAX_VALUE;
-
- range->encoding_size[0] = 5;
- range->encoding_size[1] = 13;
- range->num_encoding_sizes = 2;
- range->max_encoding_tokens = 4;
-
- /*
- * Right now we support only "iwconfig ethX power on|off"
- */
- range->pm_capa = IW_POWER_ON;
-
- /*
- * Minimum version we recommend
- */
- range->we_version_source = 15;
-
- /*
- * Version we are compiled with
- */
- range->we_version_compiled = WIRELESS_EXT;
-
- range->retry_capa = IW_RETRY_LIMIT;
- range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-
- range->min_retry = TX_RETRY_MIN;
- range->max_retry = TX_RETRY_MAX;
-
- /*
- * Set the qual, level and noise range values
- */
- range->max_qual.qual = 100;
- range->max_qual.level = 0;
- range->max_qual.noise = 0;
- range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-
- range->avg_qual.qual = 70;
- /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
- range->avg_qual.level = 0;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-
- range->sensitivity = 0;
-
- /*
- * Setup the supported power level ranges
- */
- memset(range->txpower, 0, sizeof(range->txpower));
- range->txpower[0] = 5;
- range->txpower[1] = 7;
- range->txpower[2] = 9;
- range->txpower[3] = 11;
- range->txpower[4] = 13;
- range->txpower[5] = 15;
- range->txpower[6] = 17;
- range->txpower[7] = 19;
-
- range->num_txpower = 8;
- range->txpower_capa = IW_TXPOW_DBM;
- range->txpower_capa |= IW_TXPOW_RANGE;
-
- range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
- IW_EVENT_CAPA_MASK(SIOCGIWAP) |
- IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
- range->event_capa[1] = IW_EVENT_CAPA_K_1;
-
- if (priv->fwcapinfo & FW_CAPINFO_WPA) {
- range->enc_capa = IW_ENC_CAPA_WPA
- | IW_ENC_CAPA_WPA2
- | IW_ENC_CAPA_CIPHER_TKIP
- | IW_ENC_CAPA_CIPHER_CCMP;
- }
-
-out:
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (!priv->ps_supported) {
- if (vwrq->disabled)
- return 0;
- else
- return -EINVAL;
- }
-
- /* PS is currently supported only in Infrastructure mode
- * Remove this check if it is to be supported in IBSS mode also
- */
-
- if (vwrq->disabled) {
- priv->psmode = LBS802_11POWERMODECAM;
- if (priv->psstate != PS_STATE_FULL_POWER) {
- lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
- }
-
- return 0;
- }
-
- if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
- lbs_deb_wext(
- "setting power timeout is not supported\n");
- return -EINVAL;
- } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
- lbs_deb_wext("setting power period not supported\n");
- return -EINVAL;
- }
-
- if (priv->psmode != LBS802_11POWERMODECAM) {
- return 0;
- }
-
- priv->psmode = LBS802_11POWERMODEMAX_PSP;
-
- if (priv->connect_status == LBS_CONNECTED) {
- lbs_ps_sleep(priv, CMD_OPTION_WAITFORRSP);
- }
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- vwrq->value = 0;
- vwrq->flags = 0;
- vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
- || priv->connect_status == LBS_DISCONNECTED;
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
-{
- enum {
- POOR = 30,
- FAIR = 60,
- GOOD = 80,
- VERY_GOOD = 90,
- EXCELLENT = 95,
- PERFECT = 100
- };
- struct lbs_private *priv = dev->priv;
- u32 rssi_qual;
- u32 tx_qual;
- u32 quality = 0;
- int stats_valid = 0;
- u8 rssi;
- u32 tx_retries;
- struct cmd_ds_802_11_get_log log;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- priv->wstats.status = priv->mode;
-
- /* If we're not associated, all quality values are meaningless */
- if ((priv->connect_status != LBS_CONNECTED) &&
- (priv->mesh_connect_status != LBS_CONNECTED))
- goto out;
-
- /* Quality by RSSI */
- priv->wstats.qual.level =
- CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
- priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-
- if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
- priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
- } else {
- priv->wstats.qual.noise =
- CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
- }
-
- lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
- lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
-
- rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
- if (rssi < 15)
- rssi_qual = rssi * POOR / 10;
- else if (rssi < 20)
- rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
- else if (rssi < 30)
- rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
- else if (rssi < 40)
- rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
- 10 + GOOD;
- else
- rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
- 10 + VERY_GOOD;
- quality = rssi_qual;
-
- /* Quality by TX errors */
- priv->wstats.discard.retries = priv->stats.tx_errors;
-
- memset(&log, 0, sizeof(log));
- log.hdr.size = cpu_to_le16(sizeof(log));
- lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
-
- tx_retries = le32_to_cpu(log.retry);
-
- if (tx_retries > 75)
- tx_qual = (90 - tx_retries) * POOR / 15;
- else if (tx_retries > 70)
- tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
- else if (tx_retries > 65)
- tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
- else if (tx_retries > 50)
- tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
- 15 + GOOD;
- else
- tx_qual = (50 - tx_retries) *
- (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
- quality = min(quality, tx_qual);
-
- priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
- priv->wstats.discard.retries = tx_retries;
- priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
-
- /* Calculate quality */
- priv->wstats.qual.qual = min_t(u8, quality, 100);
- priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
- stats_valid = 1;
-
- /* update stats asynchronously for future calls */
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- 0, 0, NULL);
-out:
- if (!stats_valid) {
- priv->wstats.miss.beacon = 0;
- priv->wstats.discard.retries = 0;
- priv->wstats.qual.qual = 0;
- priv->wstats.qual.level = 0;
- priv->wstats.qual.noise = 0;
- priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
- priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
- IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
- }
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return &priv->wstats;
-
-
-}
-
-static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
- struct iw_freq *fwrq, char *extra)
-{
- int ret = -EINVAL;
- struct lbs_private *priv = dev->priv;
- struct chan_freq_power *cfp;
- struct assoc_request * assoc_req;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- mutex_lock(&priv->lock);
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* If setting by frequency, convert to a channel */
- if (fwrq->e == 1) {
- long f = fwrq->m / 100000;
-
- cfp = find_cfp_by_band_and_freq(priv, 0, f);
- if (!cfp) {
- lbs_deb_wext("invalid freq %ld\n", f);
- goto out;
- }
-
- fwrq->e = 0;
- fwrq->m = (int) cfp->channel;
- }
-
- /* Setting by channel number */
- if (fwrq->m > 1000 || fwrq->e > 0) {
- goto out;
- }
-
- cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
- if (!cfp) {
- goto out;
- }
-
- assoc_req->channel = fwrq->m;
- ret = 0;
-
-out:
- if (ret == 0) {
- set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
- lbs_postpone_association_work(priv);
- } else {
- lbs_cancel_association_work(priv);
- }
- mutex_unlock(&priv->lock);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_mesh_set_freq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *fwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- struct chan_freq_power *cfp;
- int ret = -EINVAL;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* If setting by frequency, convert to a channel */
- if (fwrq->e == 1) {
- long f = fwrq->m / 100000;
-
- cfp = find_cfp_by_band_and_freq(priv, 0, f);
- if (!cfp) {
- lbs_deb_wext("invalid freq %ld\n", f);
- goto out;
- }
-
- fwrq->e = 0;
- fwrq->m = (int) cfp->channel;
- }
-
- /* Setting by channel number */
- if (fwrq->m > 1000 || fwrq->e > 0) {
- goto out;
- }
-
- cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
- if (!cfp) {
- goto out;
- }
-
- if (fwrq->m != priv->curbssparams.channel) {
- lbs_deb_wext("mesh channel change forces eth disconnect\n");
- if (priv->mode == IW_MODE_INFRA)
- lbs_send_deauthentication(priv);
- else if (priv->mode == IW_MODE_ADHOC)
- lbs_stop_adhoc_network(priv);
- }
- lbs_mesh_config(priv, 1, fwrq->m);
- lbs_update_channel(priv);
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- u8 new_rate = 0;
- int ret = -EINVAL;
- u8 rates[MAX_RATES + 1];
-
- lbs_deb_enter(LBS_DEB_WEXT);
- lbs_deb_wext("vwrq->value %d\n", vwrq->value);
-
- /* Auto rate? */
- if (vwrq->value == -1) {
- priv->auto_rate = 1;
- priv->cur_rate = 0;
- } else {
- if (vwrq->value % 100000)
- goto out;
-
- memset(rates, 0, sizeof(rates));
- copy_active_data_rates(priv, rates);
- new_rate = vwrq->value / 500000;
- if (!memchr(rates, new_rate, sizeof(rates))) {
- lbs_pr_alert("fixed data rate 0x%X out of range\n",
- new_rate);
- goto out;
- }
-
- priv->cur_rate = new_rate;
- priv->auto_rate = 0;
- }
-
- ret = lbs_set_data_rate(priv, new_rate);
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (priv->connect_status == LBS_CONNECTED) {
- vwrq->value = priv->cur_rate * 500000;
-
- if (priv->auto_rate)
- vwrq->fixed = 0;
- else
- vwrq->fixed = 1;
-
- } else {
- vwrq->fixed = 0;
- vwrq->value = 0;
- }
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_set_mode(struct net_device *dev,
- struct iw_request_info *info, u32 * uwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
- struct assoc_request * assoc_req;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if ( (*uwrq != IW_MODE_ADHOC)
- && (*uwrq != IW_MODE_INFRA)
- && (*uwrq != IW_MODE_AUTO)) {
- lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq);
- ret = -EINVAL;
- goto out;
- }
-
- mutex_lock(&priv->lock);
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- ret = -ENOMEM;
- lbs_cancel_association_work(priv);
- } else {
- assoc_req->mode = *uwrq;
- set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
- lbs_postpone_association_work(priv);
- lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
- }
- mutex_unlock(&priv->lock);
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-
-/**
- * @brief Get Encryption key
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param vwrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- * @return 0 --success, otherwise fail
- */
-static int lbs_get_encode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq, u8 * extra)
-{
- struct lbs_private *priv = dev->priv;
- int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
- dwrq->flags, index, dwrq->length, priv->wep_tx_keyidx);
-
- dwrq->flags = 0;
-
- /* Authentication method */
- switch (priv->secinfo.auth_mode) {
- case IW_AUTH_ALG_OPEN_SYSTEM:
- dwrq->flags = IW_ENCODE_OPEN;
- break;
-
- case IW_AUTH_ALG_SHARED_KEY:
- case IW_AUTH_ALG_LEAP:
- dwrq->flags = IW_ENCODE_RESTRICTED;
- break;
- default:
- dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
- break;
- }
-
- memset(extra, 0, 16);
-
- mutex_lock(&priv->lock);
-
- /* Default to returning current transmit key */
- if (index < 0)
- index = priv->wep_tx_keyidx;
-
- if ((priv->wep_keys[index].len) && priv->secinfo.wep_enabled) {
- memcpy(extra, priv->wep_keys[index].key,
- priv->wep_keys[index].len);
- dwrq->length = priv->wep_keys[index].len;
-
- dwrq->flags |= (index + 1);
- /* Return WEP enabled */
- dwrq->flags &= ~IW_ENCODE_DISABLED;
- } else if ((priv->secinfo.WPAenabled)
- || (priv->secinfo.WPA2enabled)) {
- /* return WPA enabled */
- dwrq->flags &= ~IW_ENCODE_DISABLED;
- dwrq->flags |= IW_ENCODE_NOKEY;
- } else {
- dwrq->flags |= IW_ENCODE_DISABLED;
- }
-
- mutex_unlock(&priv->lock);
-
- lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n",
- extra[0], extra[1], extra[2],
- extra[3], extra[4], extra[5], dwrq->length);
-
- lbs_deb_wext("return flags 0x%x\n", dwrq->flags);
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-/**
- * @brief Set Encryption key (internal)
- *
- * @param priv A pointer to private card structure
- * @param key_material A pointer to key material
- * @param key_length length of key material
- * @param index key index to set
- * @param set_tx_key Force set TX key (1 = yes, 0 = no)
- * @return 0 --success, otherwise fail
- */
-static int lbs_set_wep_key(struct assoc_request *assoc_req,
- const char *key_material,
- u16 key_length,
- u16 index,
- int set_tx_key)
-{
- int ret = 0;
- struct enc_key *pkey;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* Paranoid validation of key index */
- if (index > 3) {
- ret = -EINVAL;
- goto out;
- }
-
- /* validate max key length */
- if (key_length > KEY_LEN_WEP_104) {
- ret = -EINVAL;
- goto out;
- }
-
- pkey = &assoc_req->wep_keys[index];
-
- if (key_length > 0) {
- memset(pkey, 0, sizeof(struct enc_key));
- pkey->type = KEY_TYPE_ID_WEP;
-
- /* Standardize the key length */
- pkey->len = (key_length > KEY_LEN_WEP_40) ?
- KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
- memcpy(pkey->key, key_material, key_length);
- }
-
- if (set_tx_key) {
- /* Ensure the chosen key is valid */
- if (!pkey->len) {
- lbs_deb_wext("key not set, so cannot enable it\n");
- ret = -EINVAL;
- goto out;
- }
- assoc_req->wep_tx_keyidx = index;
- }
-
- assoc_req->secinfo.wep_enabled = 1;
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int validate_key_index(u16 def_index, u16 raw_index,
- u16 *out_index, u16 *is_default)
-{
- if (!out_index || !is_default)
- return -EINVAL;
-
- /* Verify index if present, otherwise use default TX key index */
- if (raw_index > 0) {
- if (raw_index > 4)
- return -EINVAL;
- *out_index = raw_index - 1;
- } else {
- *out_index = def_index;
- *is_default = 1;
- }
- return 0;
-}
-
-static void disable_wep(struct assoc_request *assoc_req)
-{
- int i;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* Set Open System auth mode */
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-
- /* Clear WEP keys and mark WEP as disabled */
- assoc_req->secinfo.wep_enabled = 0;
- for (i = 0; i < 4; i++)
- assoc_req->wep_keys[i].len = 0;
-
- set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
- set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
-
- lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-static void disable_wpa(struct assoc_request *assoc_req)
-{
- lbs_deb_enter(LBS_DEB_WEXT);
-
- memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key));
- assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
- set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
-
- memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key));
- assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
- set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-
- assoc_req->secinfo.WPAenabled = 0;
- assoc_req->secinfo.WPA2enabled = 0;
- set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
-
- lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-/**
- * @brief Set Encryption key
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param vwrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- * @return 0 --success, otherwise fail
- */
-static int lbs_set_encode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
- struct assoc_request * assoc_req;
- u16 is_default = 0, index = 0, set_tx_key = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- mutex_lock(&priv->lock);
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (dwrq->flags & IW_ENCODE_DISABLED) {
- disable_wep (assoc_req);
- disable_wpa (assoc_req);
- goto out;
- }
-
- ret = validate_key_index(assoc_req->wep_tx_keyidx,
- (dwrq->flags & IW_ENCODE_INDEX),
- &index, &is_default);
- if (ret) {
- ret = -EINVAL;
- goto out;
- }
-
- /* If WEP isn't enabled, or if there is no key data but a valid
- * index, set the TX key.
- */
- if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default))
- set_tx_key = 1;
-
- ret = lbs_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
- if (ret)
- goto out;
-
- if (dwrq->length)
- set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
- if (set_tx_key)
- set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
-
- if (dwrq->flags & IW_ENCODE_RESTRICTED) {
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
- } else if (dwrq->flags & IW_ENCODE_OPEN) {
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- }
-
-out:
- if (ret == 0) {
- set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
- lbs_postpone_association_work(priv);
- } else {
- lbs_cancel_association_work(priv);
- }
- mutex_unlock(&priv->lock);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Get Extended Encryption key (WPA/802.1x and WEP)
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param vwrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- * @return 0 on success, otherwise failure
- */
-static int lbs_get_encodeext(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq,
- char *extra)
-{
- int ret = -EINVAL;
- struct lbs_private *priv = dev->priv;
- struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- int index, max_key_len;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- max_key_len = dwrq->length - sizeof(*ext);
- if (max_key_len < 0)
- goto out;
-
- index = dwrq->flags & IW_ENCODE_INDEX;
- if (index) {
- if (index < 1 || index > 4)
- goto out;
- index--;
- } else {
- index = priv->wep_tx_keyidx;
- }
-
- if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
- ext->alg != IW_ENCODE_ALG_WEP) {
- if (index != 0 || priv->mode != IW_MODE_INFRA)
- goto out;
- }
-
- dwrq->flags = index + 1;
- memset(ext, 0, sizeof(*ext));
-
- if ( !priv->secinfo.wep_enabled
- && !priv->secinfo.WPAenabled
- && !priv->secinfo.WPA2enabled) {
- ext->alg = IW_ENCODE_ALG_NONE;
- ext->key_len = 0;
- dwrq->flags |= IW_ENCODE_DISABLED;
- } else {
- u8 *key = NULL;
-
- if ( priv->secinfo.wep_enabled
- && !priv->secinfo.WPAenabled
- && !priv->secinfo.WPA2enabled) {
- /* WEP */
- ext->alg = IW_ENCODE_ALG_WEP;
- ext->key_len = priv->wep_keys[index].len;
- key = &priv->wep_keys[index].key[0];
- } else if ( !priv->secinfo.wep_enabled
- && (priv->secinfo.WPAenabled ||
- priv->secinfo.WPA2enabled)) {
- /* WPA */
- struct enc_key * pkey = NULL;
-
- if ( priv->wpa_mcast_key.len
- && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
- pkey = &priv->wpa_mcast_key;
- else if ( priv->wpa_unicast_key.len
- && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
- pkey = &priv->wpa_unicast_key;
-
- if (pkey) {
- if (pkey->type == KEY_TYPE_ID_AES) {
- ext->alg = IW_ENCODE_ALG_CCMP;
- } else {
- ext->alg = IW_ENCODE_ALG_TKIP;
- }
- ext->key_len = pkey->len;
- key = &pkey->key[0];
- } else {
- ext->alg = IW_ENCODE_ALG_TKIP;
- ext->key_len = 0;
- }
- } else {
- goto out;
- }
-
- if (ext->key_len > max_key_len) {
- ret = -E2BIG;
- goto out;
- }
-
- if (ext->key_len)
- memcpy(ext->key, key, ext->key_len);
- else
- dwrq->flags |= IW_ENCODE_NOKEY;
- dwrq->flags |= IW_ENCODE_ENABLED;
- }
- ret = 0;
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Set Encryption key Extended (WPA/802.1x and WEP)
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param vwrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- * @return 0 --success, otherwise fail
- */
-static int lbs_set_encodeext(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq,
- char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
- struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- int alg = ext->alg;
- struct assoc_request * assoc_req;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- mutex_lock(&priv->lock);
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- ret = -ENOMEM;
- goto out;
- }
-
- if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
- disable_wep (assoc_req);
- disable_wpa (assoc_req);
- } else if (alg == IW_ENCODE_ALG_WEP) {
- u16 is_default = 0, index, set_tx_key = 0;
-
- ret = validate_key_index(assoc_req->wep_tx_keyidx,
- (dwrq->flags & IW_ENCODE_INDEX),
- &index, &is_default);
- if (ret)
- goto out;
-
- /* If WEP isn't enabled, or if there is no key data but a valid
- * index, or if the set-TX-key flag was passed, set the TX key.
- */
- if ( !assoc_req->secinfo.wep_enabled
- || (dwrq->length == 0 && !is_default)
- || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
- set_tx_key = 1;
-
- /* Copy key to driver */
- ret = lbs_set_wep_key(assoc_req, ext->key, ext->key_len, index,
- set_tx_key);
- if (ret)
- goto out;
-
- if (dwrq->flags & IW_ENCODE_RESTRICTED) {
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
- } else if (dwrq->flags & IW_ENCODE_OPEN) {
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- }
-
- /* Mark the various WEP bits as modified */
- set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
- if (dwrq->length)
- set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
- if (set_tx_key)
- set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
- } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
- struct enc_key * pkey;
-
- /* validate key length */
- if (((alg == IW_ENCODE_ALG_TKIP)
- && (ext->key_len != KEY_LEN_WPA_TKIP))
- || ((alg == IW_ENCODE_ALG_CCMP)
- && (ext->key_len != KEY_LEN_WPA_AES))) {
- lbs_deb_wext("invalid size %d for key of alg "
- "type %d\n",
- ext->key_len,
- alg);
- ret = -EINVAL;
- goto out;
- }
-
- if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
- pkey = &assoc_req->wpa_mcast_key;
- set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
- } else {
- pkey = &assoc_req->wpa_unicast_key;
- set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
- }
-
- memset(pkey, 0, sizeof (struct enc_key));
- memcpy(pkey->key, ext->key, ext->key_len);
- pkey->len = ext->key_len;
- if (pkey->len)
- pkey->flags |= KEY_INFO_WPA_ENABLED;
-
- /* Do this after zeroing key structure */
- if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
- pkey->flags |= KEY_INFO_WPA_MCAST;
- } else {
- pkey->flags |= KEY_INFO_WPA_UNICAST;
- }
-
- if (alg == IW_ENCODE_ALG_TKIP) {
- pkey->type = KEY_TYPE_ID_TKIP;
- } else if (alg == IW_ENCODE_ALG_CCMP) {
- pkey->type = KEY_TYPE_ID_AES;
- }
-
- /* If WPA isn't enabled yet, do that now */
- if ( assoc_req->secinfo.WPAenabled == 0
- && assoc_req->secinfo.WPA2enabled == 0) {
- assoc_req->secinfo.WPAenabled = 1;
- assoc_req->secinfo.WPA2enabled = 1;
- set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
- }
-
- disable_wep (assoc_req);
- }
-
-out:
- if (ret == 0) {
- lbs_postpone_association_work(priv);
- } else {
- lbs_cancel_association_work(priv);
- }
- mutex_unlock(&priv->lock);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-
-static int lbs_set_genie(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq,
- char *extra)
-{
- struct lbs_private *priv = dev->priv;
- int ret = 0;
- struct assoc_request * assoc_req;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- mutex_lock(&priv->lock);
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (dwrq->length > MAX_WPA_IE_LEN ||
- (dwrq->length && extra == NULL)) {
- ret = -EINVAL;
- goto out;
- }
-
- if (dwrq->length) {
- memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length);
- assoc_req->wpa_ie_len = dwrq->length;
- } else {
- memset(&assoc_req->wpa_ie[0], 0, sizeof(priv->wpa_ie));
- assoc_req->wpa_ie_len = 0;
- }
-
-out:
- if (ret == 0) {
- set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
- lbs_postpone_association_work(priv);
- } else {
- lbs_cancel_association_work(priv);
- }
- mutex_unlock(&priv->lock);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_genie(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq,
- char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (priv->wpa_ie_len == 0) {
- dwrq->length = 0;
- goto out;
- }
-
- if (dwrq->length < priv->wpa_ie_len) {
- ret = -E2BIG;
- goto out;
- }
-
- dwrq->length = priv->wpa_ie_len;
- memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
-
-out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-
-static int lbs_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *dwrq,
- char *extra)
-{
- struct lbs_private *priv = dev->priv;
- struct assoc_request * assoc_req;
- int ret = 0;
- int updated = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- mutex_lock(&priv->lock);
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- ret = -ENOMEM;
- goto out;
- }
-
- switch (dwrq->flags & IW_AUTH_INDEX) {
- case IW_AUTH_TKIP_COUNTERMEASURES:
- case IW_AUTH_CIPHER_PAIRWISE:
- case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_KEY_MGMT:
- case IW_AUTH_DROP_UNENCRYPTED:
- /*
- * libertas does not use these parameters
- */
- break;
-
- case IW_AUTH_WPA_VERSION:
- if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
- assoc_req->secinfo.WPAenabled = 0;
- assoc_req->secinfo.WPA2enabled = 0;
- disable_wpa (assoc_req);
- }
- if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
- assoc_req->secinfo.WPAenabled = 1;
- assoc_req->secinfo.wep_enabled = 0;
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- }
- if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
- assoc_req->secinfo.WPA2enabled = 1;
- assoc_req->secinfo.wep_enabled = 0;
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- }
- updated = 1;
- break;
-
- case IW_AUTH_80211_AUTH_ALG:
- if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
- } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- } else if (dwrq->value & IW_AUTH_ALG_LEAP) {
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP;
- } else {
- ret = -EINVAL;
- }
- updated = 1;
- break;
-
- case IW_AUTH_WPA_ENABLED:
- if (dwrq->value) {
- if (!assoc_req->secinfo.WPAenabled &&
- !assoc_req->secinfo.WPA2enabled) {
- assoc_req->secinfo.WPAenabled = 1;
- assoc_req->secinfo.WPA2enabled = 1;
- assoc_req->secinfo.wep_enabled = 0;
- assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- }
- } else {
- assoc_req->secinfo.WPAenabled = 0;
- assoc_req->secinfo.WPA2enabled = 0;
- disable_wpa (assoc_req);
- }
- updated = 1;
- break;
-
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
-out:
- if (ret == 0) {
- if (updated)
- set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
- lbs_postpone_association_work(priv);
- } else if (ret != -EOPNOTSUPP) {
- lbs_cancel_association_work(priv);
- }
- mutex_unlock(&priv->lock);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_auth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *dwrq,
- char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- switch (dwrq->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- dwrq->value = 0;
- if (priv->secinfo.WPAenabled)
- dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
- if (priv->secinfo.WPA2enabled)
- dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
- if (!dwrq->value)
- dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
- break;
-
- case IW_AUTH_80211_AUTH_ALG:
- dwrq->value = priv->secinfo.auth_mode;
- break;
-
- case IW_AUTH_WPA_ENABLED:
- if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
- dwrq->value = 1;
- break;
-
- default:
- ret = -EOPNOTSUPP;
- }
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-
-static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- int ret = 0;
- struct lbs_private *priv = dev->priv;
-
- u16 dbm;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (vwrq->disabled) {
- lbs_radio_ioctl(priv, RADIO_OFF);
- return 0;
- }
-
- priv->preamble = CMD_TYPE_AUTO_PREAMBLE;
-
- lbs_radio_ioctl(priv, RADIO_ON);
-
- /* Userspace check in iwrange if it should use dBm or mW,
- * therefore this should never happen... Jean II */
- if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) {
- return -EOPNOTSUPP;
- } else
- dbm = (u16) vwrq->value;
-
- /* auto tx power control */
-
- if (vwrq->fixed == 0)
- dbm = 0xffff;
-
- lbs_deb_wext("txpower set %d dbm\n", dbm);
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_RF_TX_POWER,
- CMD_ACT_TX_POWER_OPT_SET_LOW,
- CMD_OPTION_WAITFORRSP, 0, (void *)&dbm);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /*
- * Note : if dwrq->flags != 0, we should get the relevant SSID from
- * the SSID list...
- */
-
- /*
- * Get the current SSID
- */
- if (priv->connect_status == LBS_CONNECTED) {
- memcpy(extra, priv->curbssparams.ssid,
- priv->curbssparams.ssid_len);
- extra[priv->curbssparams.ssid_len] = '\0';
- } else {
- memset(extra, 0, 32);
- extra[priv->curbssparams.ssid_len] = '\0';
- }
- /*
- * If none, we may want to get the one that was set
- */
-
- dwrq->length = priv->curbssparams.ssid_len;
-
- dwrq->flags = 1; /* active */
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- int ret = 0;
- u8 ssid[IW_ESSID_MAX_SIZE];
- u8 ssid_len = 0;
- struct assoc_request * assoc_req;
- int in_ssid_len = dwrq->length;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* Check the size of the string */
- if (in_ssid_len > IW_ESSID_MAX_SIZE) {
- ret = -E2BIG;
- goto out;
- }
-
- memset(&ssid, 0, sizeof(ssid));
-
- if (!dwrq->flags || !in_ssid_len) {
- /* "any" SSID requested; leave SSID blank */
- } else {
- /* Specific SSID requested */
- memcpy(&ssid, extra, in_ssid_len);
- ssid_len = in_ssid_len;
- }
-
- if (!ssid_len) {
- lbs_deb_wext("requested any SSID\n");
- } else {
- lbs_deb_wext("requested SSID '%s'\n",
- escape_essid(ssid, ssid_len));
- }
-
-out:
- mutex_lock(&priv->lock);
- if (ret == 0) {
- /* Get or create the current association request */
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- ret = -ENOMEM;
- } else {
- /* Copy the SSID to the association request */
- memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
- assoc_req->ssid_len = ssid_len;
- set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
- lbs_postpone_association_work(priv);
- }
- }
-
- /* Cancel the association request if there was an error */
- if (ret != 0) {
- lbs_cancel_association_work(priv);
- }
-
- mutex_unlock(&priv->lock);
-
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-static int lbs_mesh_get_essid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- memcpy(extra, priv->mesh_ssid, priv->mesh_ssid_len);
-
- dwrq->length = priv->mesh_ssid_len;
-
- dwrq->flags = 1; /* active */
-
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
-}
-
-static int lbs_mesh_set_essid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- /* Check the size of the string */
- if (dwrq->length > IW_ESSID_MAX_SIZE) {
- ret = -E2BIG;
- goto out;
- }
-
- if (!dwrq->flags || !dwrq->length) {
- ret = -EINVAL;
- goto out;
- } else {
- /* Specific SSID requested */
- memcpy(priv->mesh_ssid, extra, dwrq->length);
- priv->mesh_ssid_len = dwrq->length;
- }
-
- lbs_mesh_config(priv, 1, priv->curbssparams.channel);
- out:
- lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief Connect to the AP or Ad-hoc Network with specific bssid
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param awrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- * @return 0 --success, otherwise fail
- */
-static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
- struct sockaddr *awrq, char *extra)
-{
- struct lbs_private *priv = dev->priv;
- struct assoc_request * assoc_req;
- int ret = 0;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
- if (awrq->sa_family != ARPHRD_ETHER)
- return -EINVAL;
-
- lbs_deb_wext("ASSOC: WAP: sa_data %s\n", print_mac(mac, awrq->sa_data));
-
- mutex_lock(&priv->lock);
-
- /* Get or create the current association request */
- assoc_req = lbs_get_association_request(priv);
- if (!assoc_req) {
- lbs_cancel_association_work(priv);
- ret = -ENOMEM;
- } else {
- /* Copy the BSSID to the association request */
- memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
- set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
- lbs_postpone_association_work(priv);
- }
-
- mutex_unlock(&priv->lock);
-
- return ret;
-}
-
-/*
- * iwconfig settable callbacks
- */
-static const iw_handler lbs_handler[] = {
- (iw_handler) NULL, /* SIOCSIWCOMMIT */
- (iw_handler) lbs_get_name, /* SIOCGIWNAME */
- (iw_handler) NULL, /* SIOCSIWNWID */
- (iw_handler) NULL, /* SIOCGIWNWID */
- (iw_handler) lbs_set_freq, /* SIOCSIWFREQ */
- (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
- (iw_handler) lbs_set_mode, /* SIOCSIWMODE */
- (iw_handler) lbs_get_mode, /* SIOCGIWMODE */
- (iw_handler) NULL, /* SIOCSIWSENS */
- (iw_handler) NULL, /* SIOCGIWSENS */
- (iw_handler) NULL, /* SIOCSIWRANGE */
- (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
- (iw_handler) NULL, /* SIOCSIWPRIV */
- (iw_handler) NULL, /* SIOCGIWPRIV */
- (iw_handler) NULL, /* SIOCSIWSTATS */
- (iw_handler) NULL, /* SIOCGIWSTATS */
- iw_handler_set_spy, /* SIOCSIWSPY */
- iw_handler_get_spy, /* SIOCGIWSPY */
- iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
- iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
- (iw_handler) lbs_set_wap, /* SIOCSIWAP */
- (iw_handler) lbs_get_wap, /* SIOCGIWAP */
- (iw_handler) NULL, /* SIOCSIWMLME */
- (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
- (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
- (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
- (iw_handler) lbs_set_essid, /* SIOCSIWESSID */
- (iw_handler) lbs_get_essid, /* SIOCGIWESSID */
- (iw_handler) lbs_set_nick, /* SIOCSIWNICKN */
- (iw_handler) lbs_get_nick, /* SIOCGIWNICKN */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
- (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
- (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
- (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
- (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
- (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
- (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
- (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
- (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
- (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
- (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
- (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
- (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
- (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
- (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
- (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
- (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
- (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
- (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
- (iw_handler) NULL, /* SIOCSIWPMKSA */
-};
-
-static const iw_handler mesh_wlan_handler[] = {
- (iw_handler) NULL, /* SIOCSIWCOMMIT */
- (iw_handler) lbs_get_name, /* SIOCGIWNAME */
- (iw_handler) NULL, /* SIOCSIWNWID */
- (iw_handler) NULL, /* SIOCGIWNWID */
- (iw_handler) lbs_mesh_set_freq, /* SIOCSIWFREQ */
- (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
- (iw_handler) NULL, /* SIOCSIWMODE */
- (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */
- (iw_handler) NULL, /* SIOCSIWSENS */
- (iw_handler) NULL, /* SIOCGIWSENS */
- (iw_handler) NULL, /* SIOCSIWRANGE */
- (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
- (iw_handler) NULL, /* SIOCSIWPRIV */
- (iw_handler) NULL, /* SIOCGIWPRIV */
- (iw_handler) NULL, /* SIOCSIWSTATS */
- (iw_handler) NULL, /* SIOCGIWSTATS */
- iw_handler_set_spy, /* SIOCSIWSPY */
- iw_handler_get_spy, /* SIOCGIWSPY */
- iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
- iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
- (iw_handler) NULL, /* SIOCSIWAP */
- (iw_handler) NULL, /* SIOCGIWAP */
- (iw_handler) NULL, /* SIOCSIWMLME */
- (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
- (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
- (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
- (iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */
- (iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */
- (iw_handler) NULL, /* SIOCSIWNICKN */
- (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
- (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
- (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
- (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
- (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
- (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
- (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
- (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
- (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
- (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
- (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
- (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
- (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
- (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* -- hole -- */
- (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
- (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
- (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
- (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
- (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
- (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
- (iw_handler) NULL, /* SIOCSIWPMKSA */
-};
-
-#define INT_PARAM (IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1)
-#define INT16_PARAM (IW_PRIV_TYPE_INT | 16)
-#define CHAR128_PARAM (IW_PRIV_TYPE_CHAR | 128)
-
-static const struct iw_priv_args lbs_private_args[] = {
- /* { cmd, set_args, get_args, name } */
- { LBS_SETNONE_GETNONE, 0, 0, "" },
- { LBS_SUBCMD_FWT_RESET, 0, 0, "fwt_reset"},
- { LBS_SUBCMD_BT_RESET, 0, 0, "bt_reset"},
- { LBS_SETNONE_GETONEINT, 0, INT_PARAM, ""},
- { LBS_SUBCMD_GET_REGION, 0, INT_PARAM, "getregioncode"},
- { LBS_SUBCMD_FWT_CLEANUP, 0, INT_PARAM, "fwt_cleanup"},
- { LBS_SUBCMD_FWT_TIME, 0, INT_PARAM, "fwt_time"},
- { LBS_SUBCMD_MESH_GET_TTL, 0, INT_PARAM, "mesh_get_ttl"},
- { LBS_SUBCMD_BT_GET_INVERT, 0, INT_PARAM, "bt_get_invert"},
- { LBS_SUBCMD_MESH_GET_BCAST_RATE, 0, INT_PARAM, "mesh_get_bcastr"},
- { LBS_SUBCMD_MESH_GET_RREQ_DELAY, 0, INT_PARAM, "get_rreq_delay"},
- { LBS_SUBCMD_MESH_GET_ROUTE_EXP, 0, INT_PARAM, "get_route_exp"},
- { LBS_SETONEINT_GETNONE, INT_PARAM, 0, ""},
- { LBS_SUBCMD_SET_REGION, INT_PARAM, 0, "setregioncode"},
- { LBS_SUBCMD_MESH_SET_TTL, INT_PARAM, 0, "mesh_set_ttl"},
- { LBS_SUBCMD_BT_SET_INVERT, INT_PARAM, 0, "bt_set_invert"},
- { LBS_SUBCMD_MESH_SET_BCAST_RATE, INT_PARAM, 0, "mesh_set_bcastr"},
- { LBS_SUBCMD_MESH_SET_RREQ_DELAY, INT_PARAM, 0, "set_rreq_delay"},
- { LBS_SUBCMD_MESH_SET_ROUTE_EXP, INT_PARAM, 0, "set_route_exp"},
- { LBS_SET128CHAR_GET128CHAR, CHAR128_PARAM, CHAR128_PARAM, ""},
- { LBS_SUBCMD_BT_ADD, CHAR128_PARAM, CHAR128_PARAM, "bt_add"},
- { LBS_SUBCMD_BT_DEL, CHAR128_PARAM, CHAR128_PARAM, "bt_del"},
- { LBS_SUBCMD_BT_LIST, CHAR128_PARAM, CHAR128_PARAM, "bt_list"},
- { LBS_SUBCMD_FWT_ADD, CHAR128_PARAM, CHAR128_PARAM, "fwt_add"},
- { LBS_SUBCMD_FWT_DEL, CHAR128_PARAM, CHAR128_PARAM, "fwt_del"},
- { LBS_SUBCMD_FWT_LOOKUP, CHAR128_PARAM, CHAR128_PARAM, "fwt_lookup"},
- { LBS_SUBCMD_FWT_LIST_NEIGHBOR, CHAR128_PARAM, CHAR128_PARAM, "fwt_list_neigh"},
- { LBS_SUBCMD_FWT_LIST, CHAR128_PARAM, CHAR128_PARAM, "fwt_list"},
- { LBS_SUBCMD_FWT_LIST_ROUTE, CHAR128_PARAM, CHAR128_PARAM, "fwt_list_route"},
- { LBS_SUBCMD_MESH_SET_LINK_COSTS, CHAR128_PARAM, CHAR128_PARAM, "set_link_costs"},
- { LBS_SUBCMD_MESH_GET_LINK_COSTS, CHAR128_PARAM, CHAR128_PARAM, "get_link_costs"},
- { LBS_SET_GET_SIXTEEN_INT, INT16_PARAM, INT16_PARAM, ""},
- { LBS_LED_GPIO_CTRL, INT16_PARAM, INT16_PARAM, "ledgpio"},
- { LBS_BCN_CTRL, INT16_PARAM, INT16_PARAM, "bcn_control"},
- { LBS_LED_BEHAVIOR_CTRL, INT16_PARAM, INT16_PARAM, "ledbhv"},
-};
-
-
-struct iw_handler_def lbs_handler_def = {
- .num_standard = ARRAY_SIZE(lbs_handler),
- .standard = (iw_handler *) lbs_handler,
- .get_wireless_stats = lbs_get_wireless_stats,
- .num_private_args = ARRAY_SIZE(lbs_private_args),
- .private_args = lbs_private_args,
-};
-
-struct iw_handler_def mesh_handler_def = {
- .num_standard = ARRAY_SIZE(mesh_wlan_handler),
- .standard = (iw_handler *) mesh_wlan_handler,
- .get_wireless_stats = lbs_get_wireless_stats,
- .num_private_args = ARRAY_SIZE(lbs_private_args),
- .private_args = lbs_private_args,
-};
+++ /dev/null
-/**
- * This file contains definition for IOCTL call.
- */
-#ifndef _LBS_WEXT_H_
-#define _LBS_WEXT_H_
-
-extern struct iw_handler_def lbs_handler_def;
-extern struct iw_handler_def mesh_handler_def;
-
-#endif
source "$(SOURCE)/Config.in.ath9k"
endef
+
+USB8388FW_NAME:=usb8388
+USB8388FW_VERSION:=5.110.22.p23
+
+define Download/usb8388
+ URL:=http://dev.laptop.org/pub/firmware/libertas/
+ FILE:=$(USB8388FW_NAME)-$(USB8388FW_VERSION).bin
+ MD5SUM=5e38f55719df3d0c58dd3bd02575a09c
+endef
+$(eval $(call Download,usb8388))
+
+define KernelPackage/libertas
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= @USB_SUPPORT +kmod-mac8021 +kmod-usb-core1
+ TITLE:=Marvell 88W8015 Wireless Driver
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/usb8xxx.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD:=$(call AutoLoad,27,libertas usb8xxx)
+endef
+
+
define KernelPackage/ar9170
$(call KernelPackage/mac80211/Default)
TITLE:=Atheros AR9170 802.11n USB support
CONFIG_MAC80211_HWSIM=$(if $(CONFIG_PACKAGE_kmod-mac80211-hwsim),m) \
CONFIG_PCMCIA= \
CONFIG_LIBIPW= \
- CONFIG_LIBERTAS= \
+ CONFIG_LIBERTAS=$(if $(CONFIG_PACKAGE_kmod-libertas),m) \
CONFIG_LIBERTAS_CS= \
CONFIG_LIBERTAS_SDIO= \
CONFIG_LIBERTAS_THINFIRM= \
+ CONFIG_LIBERTAS_USB=$(if $(CONFIG_PACKAGE_kmod-libertas),m) \
CONFIG_IPW2100= \
CONFIG_IPW2200= \
CONFIG_NL80211=y \
$(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/
endef
+define KernelPackage/libertas/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(USB8388FW_NAME)-$(USB8388FW_VERSION).bin $(1)/lib/firmware/$(USB8388FW_NAME).bin
+endef
+
define KernelPackage/mac80211/install
$(INSTALL_DIR) $(1)/lib/wifi
$(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
endef
$(eval $(call KernelPackage,ath5k))
+$(eval $(call KernelPackage,libertas))
$(eval $(call KernelPackage,mac80211))
$(eval $(call KernelPackage,p54-common))
$(eval $(call KernelPackage,p54-pci))