diff options
Diffstat (limited to 'package')
41 files changed, 30 insertions, 20882 deletions
diff --git a/package/libertas/Makefile b/package/libertas/Makefile deleted file mode 100644 index 27998b0..0000000 --- a/package/libertas/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -# -# 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)) diff --git a/package/libertas/files/LICENSE b/package/libertas/files/LICENSE deleted file mode 100644 index a740952..0000000 --- a/package/libertas/files/LICENSE +++ /dev/null @@ -1,33 +0,0 @@ -Copyright (c) 2006, One Laptop per Child and Marvell Corporation. -All rights reserved. - -Redistribution. Redistribution and use in binary form, without -modification, are permitted provided that the following conditions are -met: - -* Redistributions must reproduce the above copyright notice and the - following disclaimer in the documentation and/or other materials - provided with the distribution. -* Neither the name of Marvell Corporation nor the names of its suppliers - may be used to endorse or promote products derived from this software - without specific prior written permission. -* No reverse engineering, decompilation, or disassembly of this software - 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. - -DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. diff --git a/package/libertas/patches/100-wext.patch b/package/libertas/patches/100-wext.patch deleted file mode 100644 index c2b63e0..0000000 --- a/package/libertas/patches/100-wext.patch +++ /dev/null @@ -1,144 +0,0 @@ -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; diff --git a/package/libertas/src/11d.c b/package/libertas/src/11d.c deleted file mode 100644 index 4bc46a6..0000000 --- a/package/libertas/src/11d.c +++ /dev/null @@ -1,698 +0,0 @@ -/** - * 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; -} diff --git a/package/libertas/src/11d.h b/package/libertas/src/11d.h deleted file mode 100644 index 4f4f47f..0000000 --- a/package/libertas/src/11d.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/LICENSE b/package/libertas/src/LICENSE deleted file mode 100644 index 8862742..0000000 --- a/package/libertas/src/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ - 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. - diff --git a/package/libertas/src/Makefile b/package/libertas/src/Makefile deleted file mode 100644 index b7a136f..0000000 --- a/package/libertas/src/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -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 diff --git a/package/libertas/src/README b/package/libertas/src/README deleted file mode 100644 index 2706a42..0000000 --- a/package/libertas/src/README +++ /dev/null @@ -1,646 +0,0 @@ -================================================================================ - 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. - -============================================================================== diff --git a/package/libertas/src/assoc.c b/package/libertas/src/assoc.c deleted file mode 100644 index c9c3640..0000000 --- a/package/libertas/src/assoc.c +++ /dev/null @@ -1,1913 +0,0 @@ -/* 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; -} diff --git a/package/libertas/src/assoc.h b/package/libertas/src/assoc.h deleted file mode 100644 index c516fbe..0000000 --- a/package/libertas/src/assoc.h +++ /dev/null @@ -1,39 +0,0 @@ -/* 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 */ diff --git a/package/libertas/src/cmd.c b/package/libertas/src/cmd.c deleted file mode 100644 index 8124fd9..0000000 --- a/package/libertas/src/cmd.c +++ /dev/null @@ -1,2034 +0,0 @@ -/** - * 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); - - diff --git a/package/libertas/src/cmd.h b/package/libertas/src/cmd.h deleted file mode 100644 index 3dfc2d4..0000000 --- a/package/libertas/src/cmd.h +++ /dev/null @@ -1,60 +0,0 @@ -/* 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 */ diff --git a/package/libertas/src/cmdresp.c b/package/libertas/src/cmdresp.c deleted file mode 100644 index 5abecb7..0000000 --- a/package/libertas/src/cmdresp.c +++ /dev/null @@ -1,700 +0,0 @@ -/** - * 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; -} diff --git a/package/libertas/src/compat.h b/package/libertas/src/compat.h deleted file mode 100644 index 26c6363..0000000 --- a/package/libertas/src/compat.h +++ /dev/null @@ -1,17 +0,0 @@ -#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 diff --git a/package/libertas/src/debugfs.c b/package/libertas/src/debugfs.c deleted file mode 100644 index 0aa0ce3..0000000 --- a/package/libertas/src/debugfs.c +++ /dev/null @@ -1,968 +0,0 @@ -#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 diff --git a/package/libertas/src/debugfs.h b/package/libertas/src/debugfs.h deleted file mode 100644 index f2b9c7f..0000000 --- a/package/libertas/src/debugfs.h +++ /dev/null @@ -1,10 +0,0 @@ -#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 diff --git a/package/libertas/src/decl.h b/package/libertas/src/decl.h deleted file mode 100644 index b652fa3..0000000 --- a/package/libertas/src/decl.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/defs.h b/package/libertas/src/defs.h deleted file mode 100644 index db9cc21..0000000 --- a/package/libertas/src/defs.h +++ /dev/null @@ -1,384 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/dev.h b/package/libertas/src/dev.h deleted file mode 100644 index 0d9edb9..0000000 --- a/package/libertas/src/dev.h +++ /dev/null @@ -1,404 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/ethtool.c b/package/libertas/src/ethtool.c deleted file mode 100644 index 688d60d..0000000 --- a/package/libertas/src/ethtool.c +++ /dev/null @@ -1,196 +0,0 @@ -#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, -}; - diff --git a/package/libertas/src/host.h b/package/libertas/src/host.h deleted file mode 100644 index 3915c31..0000000 --- a/package/libertas/src/host.h +++ /dev/null @@ -1,292 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/hostcmd.h b/package/libertas/src/hostcmd.h deleted file mode 100644 index 71d9a55..0000000 --- a/package/libertas/src/hostcmd.h +++ /dev/null @@ -1,730 +0,0 @@ -/* - * 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 diff --git a/package/libertas/src/if_cs.c b/package/libertas/src/if_cs.c deleted file mode 100644 index 54280e2..0000000 --- a/package/libertas/src/if_cs.c +++ /dev/null @@ -1,932 +0,0 @@ -/* - - 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); diff --git a/package/libertas/src/if_sdio.c b/package/libertas/src/if_sdio.c deleted file mode 100644 index 51f664b..0000000 --- a/package/libertas/src/if_sdio.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * 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"); diff --git a/package/libertas/src/if_sdio.h b/package/libertas/src/if_sdio.h deleted file mode 100644 index 533bdfb..0000000 --- a/package/libertas/src/if_sdio.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 diff --git a/package/libertas/src/if_usb.c b/package/libertas/src/if_usb.c deleted file mode 100644 index 97a8119..0000000 --- a/package/libertas/src/if_usb.c +++ /dev/null @@ -1,967 +0,0 @@ -/** - * 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"); diff --git a/package/libertas/src/if_usb.h b/package/libertas/src/if_usb.h deleted file mode 100644 index 5771a83..0000000 --- a/package/libertas/src/if_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -#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 diff --git a/package/libertas/src/ioctl.c b/package/libertas/src/ioctl.c deleted file mode 100644 index 18aebe9..0000000 --- a/package/libertas/src/ioctl.c +++ /dev/null @@ -1,1243 +0,0 @@ -/** - * 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; -} diff --git a/package/libertas/src/ioctl.h b/package/libertas/src/ioctl.h deleted file mode 100644 index e4f835c..0000000 --- a/package/libertas/src/ioctl.h +++ /dev/null @@ -1,49 +0,0 @@ -#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); diff --git a/package/libertas/src/join.c b/package/libertas/src/join.c deleted file mode 100644 index 2d45080..0000000 --- a/package/libertas/src/join.c +++ /dev/null @@ -1,895 +0,0 @@ -/** - * 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; -} diff --git a/package/libertas/src/join.h b/package/libertas/src/join.h deleted file mode 100644 index c617d07..0000000 --- a/package/libertas/src/join.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/main.c b/package/libertas/src/main.c deleted file mode 100644 index f6820da..0000000 --- a/package/libertas/src/main.c +++ /dev/null @@ -1,1628 +0,0 @@ -/** - * 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"); diff --git a/package/libertas/src/radiotap.h b/package/libertas/src/radiotap.h deleted file mode 100644 index 5d118f4..0000000 --- a/package/libertas/src/radiotap.h +++ /dev/null @@ -1,57 +0,0 @@ -#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) - diff --git a/package/libertas/src/rx.c b/package/libertas/src/rx.c deleted file mode 100644 index 05af731..0000000 --- a/package/libertas/src/rx.c +++ /dev/null @@ -1,403 +0,0 @@ -/** - * 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; -} diff --git a/package/libertas/src/scan.c b/package/libertas/src/scan.c deleted file mode 100644 index 387d487..0000000 --- a/package/libertas/src/scan.c +++ /dev/null @@ -1,1197 +0,0 @@ -/** - * 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; -} diff --git a/package/libertas/src/scan.h b/package/libertas/src/scan.h deleted file mode 100644 index 9e07b04..0000000 --- a/package/libertas/src/scan.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/tx.c b/package/libertas/src/tx.c deleted file mode 100644 index a4972fe..0000000 --- a/package/libertas/src/tx.c +++ /dev/null @@ -1,206 +0,0 @@ -/** - * 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); diff --git a/package/libertas/src/types.h b/package/libertas/src/types.h deleted file mode 100644 index 4031be4..0000000 --- a/package/libertas/src/types.h +++ /dev/null @@ -1,255 +0,0 @@ -/** - * 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 diff --git a/package/libertas/src/wext.c b/package/libertas/src/wext.c deleted file mode 100644 index bde4f7c..0000000 --- a/package/libertas/src/wext.c +++ /dev/null @@ -1,2240 +0,0 @@ -/** - * 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, -}; diff --git a/package/libertas/src/wext.h b/package/libertas/src/wext.h deleted file mode 100644 index 4c08db4..0000000 --- a/package/libertas/src/wext.h +++ /dev/null @@ -1,10 +0,0 @@ -/** - * 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 diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index fe7c191..98658c8 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -328,6 +328,28 @@ define KernelPackage/ath9k/config 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 @@ -516,10 +538,11 @@ MAKE_OPTS:= \ 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 \ @@ -582,6 +605,11 @@ define Build/InstallDev $(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 @@ -672,6 +700,7 @@ define KernelPackage/b43legacy/install endef $(eval $(call KernelPackage,ath5k)) +$(eval $(call KernelPackage,libertas)) $(eval $(call KernelPackage,mac80211)) $(eval $(call KernelPackage,p54-common)) $(eval $(call KernelPackage,p54-pci)) |