[PATCH] Marvell Libertas 8388 802.11b/g USB driver
Add the Marvell Libertas 8388 802.11 USB driver. Signed-off-by: Marcelo Tosatti <marcelo@kvack.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Родитель
35c3404efa
Коммит
876c9d3aeb
|
@ -265,6 +265,19 @@ config IPW2200_DEBUG
|
|||
|
||||
If you are not sure, say N here.
|
||||
|
||||
config LIBERTAS_USB
|
||||
tristate "Marvell Libertas 8388 802.11a/b/g cards"
|
||||
depends on NET_RADIO && USB
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A driver for Marvell Libertas 8388 USB devices.
|
||||
|
||||
config LIBERTAS_USB_DEBUG
|
||||
bool "Enable full debugging output in the Libertas USB module."
|
||||
depends on LIBERTAS_USB
|
||||
---help---
|
||||
Debugging support.
|
||||
|
||||
config AIRO
|
||||
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
|
||||
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)
|
||||
|
|
|
@ -43,3 +43,4 @@ obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
|
|||
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
|
||||
|
||||
obj-$(CONFIG_USB_ZD1201) += zd1201.o
|
||||
obj-$(CONFIG_LIBERTAS_USB) += libertas/
|
||||
|
|
|
@ -0,0 +1,754 @@
|
|||
/**
|
||||
* 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 wlan_region_2_code(u8 * region)
|
||||
{
|
||||
u8 i;
|
||||
u8 size = sizeof(region_code_mapping)/
|
||||
sizeof(struct region_code_mapping);
|
||||
|
||||
for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
|
||||
region[i] = toupper(region[i]);
|
||||
|
||||
for (i = 0; i < size; 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 *wlan_code_2_region(u8 code)
|
||||
{
|
||||
u8 i;
|
||||
u8 size = sizeof(region_code_mapping)
|
||||
/ sizeof(struct region_code_mapping);
|
||||
for (i = 0; i < size; 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 wlan_get_chan_11d(u8 band, 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 = sizeof(channel_freq_power_UN_BG) /
|
||||
sizeof(struct chan_freq_power);
|
||||
|
||||
for (i = 0; i < cfp_no; i++) {
|
||||
if ((cfp + i)->channel == firstchan) {
|
||||
lbs_pr_debug(1, "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 wlan_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_dbg_hex("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_pr_debug(1, "11D: Found Chan:%d\n", chan);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_pr_debug(1, "11D: Not Find Chan:%d\n", chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 libertas_chan_2_freq(u8 chan, u8 band)
|
||||
{
|
||||
struct chan_freq_power *cf;
|
||||
u16 cnt;
|
||||
u16 i;
|
||||
u32 freq = 0;
|
||||
|
||||
cf = channel_freq_power_UN_BG;
|
||||
cnt =
|
||||
sizeof(channel_freq_power_UN_BG) /
|
||||
sizeof(struct chan_freq_power);
|
||||
|
||||
for (i = 0; i < cnt; 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 wlan_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_pr_debug(1, "11D:nrchan=%d\n", nr_chan);
|
||||
lbs_dbg_hex("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_pr_debug(1, "nr_subband=%x\n", domaininfo->nr_subband);
|
||||
lbs_dbg_hex("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 wlan_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_pr_debug(1, "11D: region_chan is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cfp = region_chan->CFP;
|
||||
if (cfp == NULL) {
|
||||
lbs_pr_debug(1, "11D: cfp equal NULL \n");
|
||||
return;
|
||||
}
|
||||
|
||||
parsed_region_chan->band = region_chan->band;
|
||||
parsed_region_chan->region = region_chan->region;
|
||||
memcpy(parsed_region_chan->countrycode,
|
||||
wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
|
||||
|
||||
lbs_pr_debug(1, "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_pr_debug(1, "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_pr_debug(1, "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 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
|
||||
{
|
||||
struct chan_freq_power *cfp;
|
||||
int cfp_no;
|
||||
u8 idx;
|
||||
|
||||
ENTER();
|
||||
|
||||
cfp = libertas_get_region_cfp_table(region, band, &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) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*chan is not in the region table */
|
||||
LEAVE();
|
||||
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 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;
|
||||
|
||||
ENTER();
|
||||
|
||||
/*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_dbg_hex("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 */
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Step1: check region_code */
|
||||
parsed_region_chan->region = region =
|
||||
wlan_region_2_code(countryinfo->countrycode);
|
||||
|
||||
lbs_pr_debug(1, "regioncode=%x\n", (u8) parsed_region_chan->region);
|
||||
lbs_dbg_hex("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_pr_debug(1, "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 (!wlan_get_chan_11d(band, firstchan, i, &curchan)) {
|
||||
/* Chan is not found in UN table */
|
||||
lbs_pr_debug(1, "chan is not supported: %d \n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
lastchan = curchan;
|
||||
|
||||
if (wlan_region_chan_supported_11d
|
||||
(region, band, 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_pr_debug(1,
|
||||
"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_pr_debug(1, "nrchan=%x\n", parsed_region_chan->nr_chan);
|
||||
lbs_dbg_hex("11D:parsed_region_chan:", (u8 *) parsed_region_chan,
|
||||
2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
|
||||
|
||||
LEAVE();
|
||||
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 libertas_get_scan_type_11d(u8 chan,
|
||||
struct parsed_region_chan_11d * parsed_region_chan)
|
||||
{
|
||||
u8 scan_type = cmd_scan_type_passive;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (wlan_channel_known_11d(chan, parsed_region_chan)) {
|
||||
lbs_pr_debug(1, "11D: Found and do Active Scan\n");
|
||||
scan_type = cmd_scan_type_active;
|
||||
} else {
|
||||
lbs_pr_debug(1, "11D: Not Find and do Passive Scan\n");
|
||||
}
|
||||
|
||||
LEAVE();
|
||||
return scan_type;
|
||||
|
||||
}
|
||||
|
||||
void libertas_init_11d(wlan_private * priv)
|
||||
{
|
||||
priv->adapter->enable11d = 0;
|
||||
memset(&(priv->adapter->parsed_region_chan), 0,
|
||||
sizeof(struct parsed_region_chan_11d));
|
||||
return;
|
||||
}
|
||||
|
||||
static int wlan_enable_11d(wlan_private * priv, u8 flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
priv->adapter->enable11d = flag;
|
||||
|
||||
/* send cmd to FW to enable/disable 11D function in FW */
|
||||
ret = libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_snmp_mib,
|
||||
cmd_act_set,
|
||||
cmd_option_waitforrsp,
|
||||
OID_802_11D_ENABLE,
|
||||
&priv->adapter->enable11d);
|
||||
if (ret)
|
||||
lbs_pr_debug(1, "11D: Fail to enable 11D \n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function sets DOMAIN INFO to FW
|
||||
* @param priv pointer to wlan_private
|
||||
* @return 0; -1
|
||||
*/
|
||||
static int set_domain_info_11d(wlan_private * priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!priv->adapter->enable11d) {
|
||||
lbs_pr_debug(1, "11D: dnld domain Info with 11d disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = libertas_prepare_and_send_command(priv, cmd_802_11d_domain_info,
|
||||
cmd_act_set,
|
||||
cmd_option_waitforrsp, 0, NULL);
|
||||
if (ret)
|
||||
lbs_pr_debug(1, "11D: Fail to dnld domain Info\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function setups scan channels
|
||||
* @param priv pointer to wlan_private
|
||||
* @param band band
|
||||
* @return 0
|
||||
*/
|
||||
int libertas_set_universaltable(wlan_private * priv, u8 band)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
u16 size = sizeof(struct chan_freq_power);
|
||||
u16 i = 0;
|
||||
|
||||
memset(adapter->universal_channel, 0,
|
||||
sizeof(adapter->universal_channel));
|
||||
|
||||
adapter->universal_channel[i].nrcfp =
|
||||
sizeof(channel_freq_power_UN_BG) / size;
|
||||
lbs_pr_debug(1, "11D: BG-band nrcfp=%d\n",
|
||||
adapter->universal_channel[i].nrcfp);
|
||||
|
||||
adapter->universal_channel[i].CFP = channel_freq_power_UN_BG;
|
||||
adapter->universal_channel[i].valid = 1;
|
||||
adapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
|
||||
adapter->universal_channel[i].band = band;
|
||||
i++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function implements command CMD_802_11D_DOMAIN_INFO
|
||||
* @param priv pointer to wlan_private
|
||||
* @param cmd pointer to cmd buffer
|
||||
* @param cmdno cmd ID
|
||||
* @param cmdOption cmd action
|
||||
* @return 0
|
||||
*/
|
||||
int libertas_cmd_802_11d_domain_info(wlan_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;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
u8 nr_subband = adapter->domainreg.nr_subband;
|
||||
|
||||
ENTER();
|
||||
|
||||
lbs_pr_debug(1, "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_dbg_hex("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd,
|
||||
(int)(cmd->size));
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
|
||||
memcpy(domain->countrycode, adapter->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, adapter->domainreg.subband,
|
||||
nr_subband * sizeof(struct ieeetypes_subbandset));
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
|
||||
domain->header.len +
|
||||
sizeof(struct mrvlietypesheader) +
|
||||
S_DS_GEN);
|
||||
} else {
|
||||
cmd->size =
|
||||
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
|
||||
}
|
||||
|
||||
lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->size));
|
||||
|
||||
LEAVE();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function implements private cmd: enable/disable 11D
|
||||
* @param priv pointer to wlan_private
|
||||
* @param wrq pointer to user data
|
||||
* @return 0 or -1
|
||||
*/
|
||||
int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq)
|
||||
{
|
||||
int data = 0;
|
||||
int *val;
|
||||
|
||||
ENTER();
|
||||
data = SUBCMD_DATA(wrq);
|
||||
|
||||
lbs_pr_debug(1, "enable 11D: %s\n",
|
||||
(data == 1) ? "enable" : "Disable");
|
||||
|
||||
wlan_enable_11d(priv, data);
|
||||
val = (int *)wrq->u.name;
|
||||
*val = priv->adapter->enable11d;
|
||||
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function parses countryinfo from AP and download country info to FW
|
||||
* @param priv pointer to wlan_private
|
||||
* @param resp pointer to command response buffer
|
||||
* @return 0; -1
|
||||
*/
|
||||
int libertas_ret_802_11d_domain_info(wlan_private * priv,
|
||||
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;
|
||||
|
||||
ENTER();
|
||||
|
||||
lbs_dbg_hex("11D DOMAIN Info Rsp Data:", (u8 *) resp,
|
||||
(int)le16_to_cpu(resp->size));
|
||||
|
||||
nr_subband = (domain->header.len - 3) / sizeof(struct ieeetypes_subbandset);
|
||||
/* countrycode 3 bytes */
|
||||
|
||||
lbs_pr_debug(1, "11D Domain Info Resp: nr_subband=%d\n", nr_subband);
|
||||
|
||||
if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
|
||||
lbs_pr_debug(1, "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_pr_debug(1, "Invalid action:%d\n", domaininfo->action);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function parses countryinfo from AP and download country info to FW
|
||||
* @param priv pointer to wlan_private
|
||||
* @return 0; -1
|
||||
*/
|
||||
int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
|
||||
{
|
||||
int ret;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
|
||||
ENTER();
|
||||
if (priv->adapter->enable11d) {
|
||||
memset(&adapter->parsed_region_chan, 0,
|
||||
sizeof(struct parsed_region_chan_11d));
|
||||
ret = parse_domain_info_11d(&adapter->pattemptedbssdesc->
|
||||
countryinfo, 0,
|
||||
&adapter->parsed_region_chan);
|
||||
|
||||
if (ret == -1) {
|
||||
lbs_pr_debug(1, "11D: Err Parse domain_info from AP..\n");
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&adapter->domainreg, 0,
|
||||
sizeof(struct wlan_802_11d_domain_reg));
|
||||
generate_domain_info_11d(&adapter->parsed_region_chan,
|
||||
&adapter->domainreg);
|
||||
|
||||
ret = set_domain_info_11d(priv);
|
||||
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function generates 11D info from user specified regioncode and download to FW
|
||||
* @param priv pointer to wlan_private
|
||||
* @return 0; -1
|
||||
*/
|
||||
int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
|
||||
{
|
||||
int ret;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
struct region_channel *region_chan;
|
||||
u8 j;
|
||||
|
||||
ENTER();
|
||||
lbs_pr_debug(1, "11D:curbssparams.band[%d]\n", adapter->curbssparams.band);
|
||||
|
||||
if (priv->adapter->enable11d) {
|
||||
/* update parsed_region_chan_11; dnld domaininf to FW */
|
||||
|
||||
for (j = 0; j < sizeof(adapter->region_channel) /
|
||||
sizeof(adapter->region_channel[0]); j++) {
|
||||
region_chan = &adapter->region_channel[j];
|
||||
|
||||
lbs_pr_debug(1, "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 != adapter->curbssparams.band)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= sizeof(adapter->region_channel) /
|
||||
sizeof(adapter->region_channel[0])) {
|
||||
lbs_pr_debug(1, "11D:region_chan not found. band[%d]\n",
|
||||
adapter->curbssparams.band);
|
||||
LEAVE();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&adapter->parsed_region_chan, 0,
|
||||
sizeof(struct parsed_region_chan_11d));
|
||||
wlan_generate_parsed_region_chan_11d(region_chan,
|
||||
&adapter->
|
||||
parsed_region_chan);
|
||||
|
||||
memset(&adapter->domainreg, 0,
|
||||
sizeof(struct wlan_802_11d_domain_reg));
|
||||
generate_domain_info_11d(&adapter->parsed_region_chan,
|
||||
&adapter->domainreg);
|
||||
|
||||
ret = set_domain_info_11d(priv);
|
||||
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* This header file contains data structures and
|
||||
* function declarations of 802.11d
|
||||
*/
|
||||
#ifndef _WLAN_11D_
|
||||
#define _WLAN_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 {
|
||||
u16 action;
|
||||
struct mrvlietypes_domainparamset domain;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/** domain regulatory information */
|
||||
struct wlan_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;
|
||||
};
|
||||
|
||||
u8 libertas_get_scan_type_11d(u8 chan,
|
||||
struct parsed_region_chan_11d *parsed_region_chan);
|
||||
|
||||
u32 libertas_chan_2_freq(u8 chan, u8 band);
|
||||
|
||||
enum state_11d libertas_get_state_11d(wlan_private * priv);
|
||||
|
||||
void libertas_init_11d(wlan_private * priv);
|
||||
|
||||
int libertas_set_universaltable(wlan_private * priv, u8 band);
|
||||
|
||||
int libertas_cmd_802_11d_domain_info(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd, u16 cmdno,
|
||||
u16 cmdOption);
|
||||
|
||||
int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq);
|
||||
|
||||
int libertas_ret_802_11d_domain_info(wlan_private * priv,
|
||||
struct cmd_ds_command *resp);
|
||||
|
||||
int libertas_parse_dnld_countryinfo_11d(wlan_private * priv);
|
||||
|
||||
int libertas_create_dnld_countryinfo_11d(wlan_private * priv);
|
||||
|
||||
#endif /* _WLAN_11D_ */
|
|
@ -0,0 +1,16 @@
|
|||
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.
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# EXTRA_CFLAGS += -Wpacked
|
||||
|
||||
usb8xxx-objs := main.o fw.o wext.o \
|
||||
rx.o tx.o cmd.o \
|
||||
cmdresp.o scan.o \
|
||||
join.o 11d.o \
|
||||
ioctl.o debugfs.o \
|
||||
ethtool.o assoc.o
|
||||
|
||||
ifeq ($(CONFIG_LIBERTAS_USB_DEBUG), y)
|
||||
EXTRA_CFLAGS += -DDEBUG -DPROC_DEBUG
|
||||
endif
|
||||
|
||||
|
||||
# This is needed to support the newer boot2 bootloader (v >= 3104)
|
||||
EXTRA_CFLAGS += -DSUPPORT_BOOT_COMMAND
|
||||
usb8xxx-objs += if_bootcmd.o
|
||||
usb8xxx-objs += if_usb.o
|
||||
|
||||
obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,588 @@
|
|||
/* Copyright (C) 2006, Red Hat, Inc. */
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
#include "assoc.h"
|
||||
#include "join.h"
|
||||
#include "decl.h"
|
||||
#include "hostcmd.h"
|
||||
#include "host.h"
|
||||
|
||||
|
||||
static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
static int assoc_helper_essid(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
ENTER();
|
||||
|
||||
lbs_pr_debug(1, "New SSID requested: %s\n", assoc_req->ssid.ssid);
|
||||
if (assoc_req->mode == wlan802_11infrastructure) {
|
||||
if (adapter->prescan) {
|
||||
libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
|
||||
}
|
||||
|
||||
i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
|
||||
NULL, wlan802_11infrastructure);
|
||||
if (i >= 0) {
|
||||
lbs_pr_debug(1,
|
||||
"SSID found in scan list ... associating...\n");
|
||||
|
||||
ret = wlan_associate(priv, &adapter->scantable[i]);
|
||||
if (ret == 0) {
|
||||
memcpy(&assoc_req->bssid,
|
||||
&adapter->scantable[i].macaddress,
|
||||
ETH_ALEN);
|
||||
}
|
||||
} else {
|
||||
lbs_pr_debug(1, "SSID '%s' not found; cannot associate\n",
|
||||
assoc_req->ssid.ssid);
|
||||
}
|
||||
} else if (assoc_req->mode == wlan802_11ibss) {
|
||||
/* Scan for the network, do not save previous results. Stale
|
||||
* scan data will cause us to join a non-existant adhoc network
|
||||
*/
|
||||
libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
|
||||
|
||||
/* Search for the requested SSID in the scan table */
|
||||
i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
|
||||
wlan802_11ibss);
|
||||
if (i >= 0) {
|
||||
lbs_pr_debug(1, "SSID found at %d in List, so join\n", ret);
|
||||
libertas_join_adhoc_network(priv, &adapter->scantable[i]);
|
||||
} else {
|
||||
/* else send START command */
|
||||
lbs_pr_debug(1, "SSID not found in list, so creating adhoc"
|
||||
" with SSID '%s'\n", assoc_req->ssid.ssid);
|
||||
libertas_start_adhoc_network(priv, &assoc_req->ssid);
|
||||
}
|
||||
memcpy(&assoc_req->bssid, &adapter->current_addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int assoc_helper_bssid(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int i, ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
lbs_pr_debug(1, "ASSOC: WAP: BSSID = " MAC_FMT "\n",
|
||||
MAC_ARG(assoc_req->bssid));
|
||||
|
||||
/* Search for index position in list for requested MAC */
|
||||
i = libertas_find_BSSID_in_list(adapter, assoc_req->bssid,
|
||||
assoc_req->mode);
|
||||
if (i < 0) {
|
||||
lbs_pr_debug(1, "ASSOC: WAP: BSSID " MAC_FMT " not found, "
|
||||
"cannot associate.\n", MAC_ARG(assoc_req->bssid));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (assoc_req->mode == wlan802_11infrastructure) {
|
||||
ret = wlan_associate(priv, &adapter->scantable[i]);
|
||||
lbs_pr_debug(1, "ASSOC: return from wlan_associate(bssd) was %d\n", ret);
|
||||
} else if (assoc_req->mode == wlan802_11ibss) {
|
||||
libertas_join_adhoc_network(priv, &adapter->scantable[i]);
|
||||
}
|
||||
memcpy(&assoc_req->ssid, &adapter->scantable[i].ssid,
|
||||
sizeof(struct WLAN_802_11_SSID));
|
||||
|
||||
out:
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int assoc_helper_associate(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
int ret = 0, done = 0;
|
||||
|
||||
/* If we're given and 'any' BSSID, try associating based on SSID */
|
||||
|
||||
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
|
||||
if (memcmp(bssid_any, assoc_req->bssid, ETH_ALEN)
|
||||
&& memcmp(bssid_off, assoc_req->bssid, ETH_ALEN)) {
|
||||
ret = assoc_helper_bssid(priv, assoc_req);
|
||||
done = 1;
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
|
||||
ret = assoc_helper_essid(priv, assoc_req);
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int assoc_helper_mode(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (assoc_req->mode == adapter->inframode) {
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (assoc_req->mode == wlan802_11infrastructure) {
|
||||
if (adapter->psstate != PS_STATE_FULL_POWER)
|
||||
libertas_ps_wakeup(priv, cmd_option_waitforrsp);
|
||||
adapter->psmode = wlan802_11powermodecam;
|
||||
}
|
||||
|
||||
adapter->inframode = assoc_req->mode;
|
||||
ret = libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_snmp_mib,
|
||||
0, cmd_option_waitforrsp,
|
||||
OID_802_11_INFRASTRUCTURE_MODE,
|
||||
(void *) assoc_req->mode);
|
||||
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int assoc_helper_wep_keys(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
/* 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 = libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_set_wep,
|
||||
cmd_act_add,
|
||||
cmd_option_waitforrsp,
|
||||
0, assoc_req);
|
||||
} else {
|
||||
ret = libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_set_wep,
|
||||
cmd_act_remove,
|
||||
cmd_option_waitforrsp,
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* enable/disable the MAC's WEP packet filter */
|
||||
if (assoc_req->secinfo.WEPstatus == wlan802_11WEPenabled)
|
||||
adapter->currentpacketfilter |= cmd_act_mac_wep_enable;
|
||||
else
|
||||
adapter->currentpacketfilter &= ~cmd_act_mac_wep_enable;
|
||||
ret = libertas_set_mac_packet_filter(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&adapter->lock);
|
||||
|
||||
/* Copy WEP keys into adapter wep key fields */
|
||||
for (i = 0; i < 4; i++) {
|
||||
memcpy(&adapter->wep_keys[i], &assoc_req->wep_keys[i],
|
||||
sizeof(struct WLAN_802_11_KEY));
|
||||
}
|
||||
adapter->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
|
||||
|
||||
mutex_unlock(&adapter->lock);
|
||||
|
||||
out:
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int assoc_helper_secinfo(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
memcpy(&adapter->secinfo, &assoc_req->secinfo,
|
||||
sizeof(struct wlan_802_11_security));
|
||||
|
||||
ret = libertas_set_mac_packet_filter(priv);
|
||||
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int assoc_helper_wpa_keys(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
/* enable/Disable RSN */
|
||||
ret = libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_enable_rsn,
|
||||
cmd_act_set,
|
||||
cmd_option_waitforrsp,
|
||||
0, assoc_req);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_key_material,
|
||||
cmd_act_set,
|
||||
cmd_option_waitforrsp,
|
||||
0, assoc_req);
|
||||
|
||||
out:
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int assoc_helper_wpa_ie(wlan_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
|
||||
memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
|
||||
adapter->wpa_ie_len = assoc_req->wpa_ie_len;
|
||||
} else {
|
||||
memset(&adapter->wpa_ie, 0, MAX_WPA_IE_LEN);
|
||||
adapter->wpa_ie_len = 0;
|
||||
}
|
||||
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int should_deauth_infrastructure(wlan_adapter *adapter,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
if (adapter->connect_status != libertas_connected)
|
||||
return 0;
|
||||
|
||||
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
|
||||
lbs_pr_debug(1, "Deauthenticating due to new SSID in "
|
||||
" configuration request.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
|
||||
if (adapter->secinfo.authmode !=
|
||||
assoc_req->secinfo.authmode) {
|
||||
lbs_pr_debug(1, "Deauthenticating due to updated security "
|
||||
"info in configuration request.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
|
||||
lbs_pr_debug(1, "Deauthenticating due to new BSSID in "
|
||||
" configuration request.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME: deal with 'auto' mode somehow */
|
||||
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
|
||||
if (assoc_req->mode != wlan802_11infrastructure)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int should_stop_adhoc(wlan_adapter *adapter,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
if (adapter->connect_status != libertas_connected)
|
||||
return 0;
|
||||
|
||||
if (adapter->curbssparams.ssid.ssidlength != assoc_req->ssid.ssidlength)
|
||||
return 1;
|
||||
if (memcmp(adapter->curbssparams.ssid.ssid, assoc_req->ssid.ssid,
|
||||
sizeof(struct WLAN_802_11_SSID)))
|
||||
return 1;
|
||||
|
||||
/* FIXME: deal with 'auto' mode somehow */
|
||||
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
|
||||
if (assoc_req->mode != wlan802_11ibss)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void wlan_association_worker(struct work_struct *work)
|
||||
{
|
||||
wlan_private *priv = container_of(work, wlan_private, assoc_work.work);
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
struct assoc_request * assoc_req = NULL;
|
||||
int ret = 0;
|
||||
int find_any_ssid = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
mutex_lock(&adapter->lock);
|
||||
assoc_req = adapter->assoc_req;
|
||||
adapter->assoc_req = NULL;
|
||||
mutex_unlock(&adapter->lock);
|
||||
|
||||
if (!assoc_req) {
|
||||
LEAVE();
|
||||
return;
|
||||
}
|
||||
|
||||
lbs_pr_debug(1, "ASSOC: starting new association request: flags = 0x%lX\n",
|
||||
assoc_req->flags);
|
||||
|
||||
/* If 'any' SSID was specified, find an SSID to associate with */
|
||||
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
|
||||
&& !assoc_req->ssid.ssidlength)
|
||||
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 (memcmp(&assoc_req->bssid, bssid_any, ETH_ALEN)
|
||||
&& memcmp(&assoc_req->bssid, bssid_off, ETH_ALEN))
|
||||
find_any_ssid = 0;
|
||||
}
|
||||
|
||||
if (find_any_ssid) {
|
||||
enum WLAN_802_11_NETWORK_INFRASTRUCTURE new_mode;
|
||||
|
||||
ret = libertas_find_best_network_SSID(priv, &assoc_req->ssid,
|
||||
assoc_req->mode, &new_mode);
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "Could not find best network\n");
|
||||
ret = -ENETUNREACH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure we switch to the mode of the AP */
|
||||
if (assoc_req->mode == wlan802_11autounknown) {
|
||||
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 (adapter->inframode == wlan802_11infrastructure) {
|
||||
if (should_deauth_infrastructure(adapter, assoc_req)) {
|
||||
ret = libertas_send_deauthentication(priv);
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "Deauthentication due to new "
|
||||
"configuration request failed: %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
} else if (adapter->inframode == wlan802_11ibss) {
|
||||
if (should_stop_adhoc(adapter, assoc_req)) {
|
||||
ret = libertas_stop_adhoc_network(priv);
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "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) {
|
||||
lbs_pr_debug(1, "ASSOC(:%d) mode: ret = %d\n", __LINE__, 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) {
|
||||
lbs_pr_debug(1, "ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
|
||||
ret = assoc_helper_secinfo(priv, assoc_req);
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
|
||||
ret = assoc_helper_wpa_ie(priv, assoc_req);
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, 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) {
|
||||
lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, 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_pr_debug(1, "ASSOC: association attempt unsuccessful: %d\n",
|
||||
ret);
|
||||
success = 0;
|
||||
}
|
||||
|
||||
if (adapter->connect_status != libertas_connected) {
|
||||
lbs_pr_debug(1, "ASSOC: assoication attempt unsuccessful, "
|
||||
"not connected.\n");
|
||||
success = 0;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
lbs_pr_debug(1, "ASSOC: association attempt successful. "
|
||||
"Associated to '%s' (" MAC_FMT ")\n",
|
||||
assoc_req->ssid.ssid, MAC_ARG(assoc_req->bssid));
|
||||
libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_rssi,
|
||||
0, cmd_option_waitforrsp, 0, NULL);
|
||||
|
||||
libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_get_log,
|
||||
0, cmd_option_waitforrsp, 0, NULL);
|
||||
} else {
|
||||
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "ASSOC: reconfiguration attempt unsuccessful: %d\n",
|
||||
ret);
|
||||
}
|
||||
kfree(assoc_req);
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Caller MUST hold any necessary locks
|
||||
*/
|
||||
struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
|
||||
{
|
||||
struct assoc_request * assoc_req;
|
||||
|
||||
if (!adapter->assoc_req) {
|
||||
adapter->assoc_req = kzalloc(sizeof(struct assoc_request), GFP_KERNEL);
|
||||
if (!adapter->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 = adapter->assoc_req;
|
||||
if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
|
||||
memcpy(&assoc_req->ssid, adapter->curbssparams.ssid.ssid,
|
||||
adapter->curbssparams.ssid.ssidlength);
|
||||
}
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
|
||||
assoc_req->channel = adapter->curbssparams.channel;
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
|
||||
assoc_req->mode = adapter->inframode;
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
|
||||
memcpy(&assoc_req->bssid, adapter->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], &adapter->wep_keys[i],
|
||||
sizeof(struct WLAN_802_11_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
|
||||
assoc_req->wep_tx_keyidx = adapter->wep_tx_keyidx;
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
|
||||
memcpy(&assoc_req->wpa_mcast_key, &adapter->wpa_mcast_key,
|
||||
sizeof(struct WLAN_802_11_KEY));
|
||||
}
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
|
||||
memcpy(&assoc_req->wpa_unicast_key, &adapter->wpa_unicast_key,
|
||||
sizeof(struct WLAN_802_11_KEY));
|
||||
}
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
|
||||
memcpy(&assoc_req->secinfo, &adapter->secinfo,
|
||||
sizeof(struct wlan_802_11_security));
|
||||
}
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
|
||||
memcpy(&assoc_req->wpa_ie, &adapter->wpa_ie,
|
||||
MAX_WPA_IE_LEN);
|
||||
assoc_req->wpa_ie_len = adapter->wpa_ie_len;
|
||||
}
|
||||
|
||||
return assoc_req;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* Copyright (C) 2006, Red Hat, Inc. */
|
||||
|
||||
#ifndef _WLAN_ASSOC_H_
|
||||
#define _WLAN_ASSOC_H_
|
||||
|
||||
#include "dev.h"
|
||||
|
||||
void wlan_association_worker(struct work_struct *work);
|
||||
|
||||
struct assoc_request * wlan_get_association_request(wlan_adapter *adapter);
|
||||
|
||||
#define ASSOC_DELAY (HZ / 2)
|
||||
static inline void wlan_postpone_association_work(wlan_private *priv)
|
||||
{
|
||||
if (priv->adapter->surpriseremoved)
|
||||
return;
|
||||
cancel_delayed_work(&priv->assoc_work);
|
||||
queue_delayed_work(priv->assoc_thread, &priv->assoc_work, ASSOC_DELAY);
|
||||
}
|
||||
|
||||
static inline void wlan_cancel_association_work(wlan_private *priv)
|
||||
{
|
||||
cancel_delayed_work(&priv->assoc_work);
|
||||
if (priv->adapter->assoc_req) {
|
||||
kfree(priv->adapter->assoc_req);
|
||||
priv->adapter->assoc_req = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _WLAN_ASSOC_H */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,6 @@
|
|||
void libertas_debugfs_init(void);
|
||||
void libertas_debugfs_remove(void);
|
||||
|
||||
void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev);
|
||||
void libertas_debugfs_remove_one(wlan_private *priv);
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* This file contains declaration referring to
|
||||
* functions defined in other source files
|
||||
*/
|
||||
|
||||
#ifndef _WLAN_DECL_H_
|
||||
#define _WLAN_DECL_H_
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/** Function Prototype Declaration */
|
||||
struct wlan_private;
|
||||
struct sk_buff;
|
||||
struct net_device;
|
||||
|
||||
extern char *libertas_fw_name;
|
||||
|
||||
void libertas_free_adapter(wlan_private * priv);
|
||||
int libertas_set_mac_packet_filter(wlan_private * priv);
|
||||
|
||||
int libertas_send_null_packet(wlan_private * priv, u8 pwr_mgmt);
|
||||
void libertas_send_tx_feedback(wlan_private * priv);
|
||||
u8 libertas_check_last_packet_indication(wlan_private * priv);
|
||||
|
||||
int libertas_free_cmd_buffer(wlan_private * priv);
|
||||
struct cmd_ctrl_node;
|
||||
struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv);
|
||||
|
||||
void libertas_set_cmd_ctrl_node(wlan_private * priv,
|
||||
struct cmd_ctrl_node *ptempnode,
|
||||
u32 cmd_oid, u16 wait_option, void *pdata_buf);
|
||||
|
||||
int libertas_prepare_and_send_command(wlan_private * priv,
|
||||
u16 cmd_no,
|
||||
u16 cmd_action,
|
||||
u16 wait_option, u32 cmd_oid, void *pdata_buf);
|
||||
|
||||
void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail);
|
||||
|
||||
int libertas_allocate_cmd_buffer(wlan_private * priv);
|
||||
int libertas_execute_next_command(wlan_private * priv);
|
||||
int libertas_process_event(wlan_private * priv);
|
||||
void libertas_interrupt(struct net_device *);
|
||||
int libertas_set_radio_control(wlan_private * priv);
|
||||
u32 libertas_index_to_data_rate(u8 index);
|
||||
u8 libertas_data_rate_to_index(u32 rate);
|
||||
void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen);
|
||||
|
||||
int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb);
|
||||
|
||||
/** The proc fs interface */
|
||||
int libertas_process_rx_command(wlan_private * priv);
|
||||
int libertas_process_tx(wlan_private * priv, struct sk_buff *skb);
|
||||
void libertas_cleanup_and_insert_cmd(wlan_private * priv,
|
||||
struct cmd_ctrl_node *ptempcmd);
|
||||
void __libertas_cleanup_and_insert_cmd(wlan_private * priv,
|
||||
struct cmd_ctrl_node *ptempcmd);
|
||||
|
||||
int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band);
|
||||
|
||||
int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *);
|
||||
|
||||
void libertas_ps_sleep(wlan_private * priv, int wait_option);
|
||||
void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode);
|
||||
void libertas_ps_wakeup(wlan_private * priv, int wait_option);
|
||||
|
||||
void libertas_tx_runqueue(wlan_private *priv);
|
||||
|
||||
extern struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
|
||||
wlan_adapter * adapter, u8 band, u16 channel);
|
||||
|
||||
extern void libertas_mac_event_disconnected(wlan_private * priv);
|
||||
|
||||
void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str);
|
||||
|
||||
int reset_device(wlan_private *priv);
|
||||
/* main.c */
|
||||
extern struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
|
||||
int *cfp_no);
|
||||
wlan_private *wlan_add_card(void *card);
|
||||
int wlan_remove_card(void *card);
|
||||
|
||||
#endif /* _WLAN_DECL_H_ */
|
|
@ -0,0 +1,369 @@
|
|||
/**
|
||||
* This header file contains global constant/enum definitions,
|
||||
* global variable declaration.
|
||||
*/
|
||||
#ifndef _WLAN_DEFS_H_
|
||||
#define _WLAN_DEFS_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
extern unsigned int libertas_debug;
|
||||
|
||||
#define DRV_NAME "usb8xxx"
|
||||
|
||||
#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
|
||||
#define lbs_pr_debug(level, format, args...) \
|
||||
do { if (libertas_debug >= level) \
|
||||
printk(KERN_INFO DRV_NAME": " format, ##args); } while (0)
|
||||
#define lbs_dev_dbg(level, device, format, args...) \
|
||||
lbs_pr_debug(level, "%s: " format, \
|
||||
(device)->bus_id , ## args)
|
||||
|
||||
static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!libertas_debug)
|
||||
return;
|
||||
|
||||
printk(KERN_DEBUG "%s: ", prompt);
|
||||
for (i = 1; i <= len; i++) {
|
||||
printk(KERN_DEBUG "%02x ", (u8) * buf);
|
||||
buf++;
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
#else
|
||||
#define lbs_pr_debug(level, format, args...) do {} while (0)
|
||||
#define lbs_dev_dbg(level, device, format, args...) do {} while (0)
|
||||
#define lbs_dbg_hex(x,y,z) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define ENTER() lbs_pr_debug(1, "Enter: %s, %s:%i\n", \
|
||||
__FUNCTION__, __FILE__, __LINE__)
|
||||
#define LEAVE() lbs_pr_debug(1, "Leave: %s, %s:%i\n", \
|
||||
__FUNCTION__, __FILE__, __LINE__)
|
||||
|
||||
/** 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 MRVDRV_NUM_OF_CMD_BUFFER 10
|
||||
#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
|
||||
#define MRVDRV_MAX_CHANNEL_SIZE 14
|
||||
#define MRVDRV_MAX_BSSID_LIST 64
|
||||
#define MRVDRV_ASSOCIATION_TIME_OUT 255
|
||||
#define MRVDRV_SNAP_HEADER_LEN 8
|
||||
|
||||
#define WLAN_UPLD_SIZE 2312
|
||||
#define DEV_NAME_LEN 32
|
||||
|
||||
/** 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_DEBUG_RX_PATH 0x00000001
|
||||
#define MRVDRV_DEBUG_TX_PATH 0x00000002
|
||||
|
||||
#define MRVDRV_MIN_BEACON_INTERVAL 20
|
||||
#define MRVDRV_MAX_BEACON_INTERVAL 1000
|
||||
#define MRVDRV_BEACON_INTERVAL 100
|
||||
|
||||
/** 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)
|
||||
|
||||
/** WPA key LENGTH*/
|
||||
#define MRVL_MAX_KEY_WPA_KEY_LENGTH 32
|
||||
|
||||
#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 B_SUPPORTED_RATES 8
|
||||
#define G_SUPPORTED_RATES 14
|
||||
|
||||
#define WLAN_SUPPORTED_RATES 14
|
||||
|
||||
#define MAX_LEDS 8
|
||||
|
||||
#define IS_MESH_FRAME(x) (x->cb[6])
|
||||
#define SET_MESH_FRAME(x) (x->cb[6]=1)
|
||||
#define UNSET_MESH_FRAME(x) (x->cb[6]=0)
|
||||
|
||||
/** Global Variable Declaration */
|
||||
typedef struct _wlan_private wlan_private;
|
||||
typedef struct _wlan_adapter wlan_adapter;
|
||||
extern const char libertas_driver_version[];
|
||||
extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE];
|
||||
|
||||
extern u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES];
|
||||
|
||||
extern u8 libertas_supported_rates[G_SUPPORTED_RATES];
|
||||
|
||||
extern u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES];
|
||||
|
||||
extern u8 libertas_adhoc_rates_b[4];
|
||||
|
||||
/** 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
|
||||
};
|
||||
|
||||
/** WLAN_802_11_AUTH_ALG*/
|
||||
enum WLAN_802_11_AUTH_ALG {
|
||||
AUTH_ALG_OPEN_SYSTEM = 1,
|
||||
AUTH_ALG_SHARED_KEY = 2,
|
||||
AUTH_ALG_NETWORK_EAP = 8,
|
||||
};
|
||||
|
||||
/** WLAN_802_1X_AUTH_ALG */
|
||||
enum WLAN_802_1X_AUTH_ALG {
|
||||
WLAN_1X_AUTH_ALG_NONE = 1,
|
||||
WLAN_1X_AUTH_ALG_LEAP = 2,
|
||||
WLAN_1X_AUTH_ALG_TLS = 4,
|
||||
WLAN_1X_AUTH_ALG_TTLS = 8,
|
||||
WLAN_1X_AUTH_ALG_MD5 = 16,
|
||||
};
|
||||
|
||||
/** WLAN_802_11_ENCRYPTION_MODE */
|
||||
enum WLAN_802_11_ENCRYPTION_MODE {
|
||||
CIPHER_NONE,
|
||||
CIPHER_WEP40,
|
||||
CIPHER_TKIP,
|
||||
CIPHER_CCMP,
|
||||
CIPHER_WEP104,
|
||||
};
|
||||
|
||||
/** WLAN_802_11_POWER_MODE */
|
||||
enum WLAN_802_11_POWER_MODE {
|
||||
wlan802_11powermodecam,
|
||||
wlan802_11powermodemax_psp,
|
||||
wlan802_11Powermodefast_psp,
|
||||
/*not a real mode, defined as an upper bound */
|
||||
wlan802_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
|
||||
};
|
||||
|
||||
/** WLAN_MEDIA_STATE */
|
||||
enum WLAN_MEDIA_STATE {
|
||||
libertas_connected,
|
||||
libertas_disconnected
|
||||
};
|
||||
|
||||
/** WLAN_802_11_PRIVACY_FILTER */
|
||||
enum WLAN_802_11_PRIVACY_FILTER {
|
||||
wlan802_11privfilteracceptall,
|
||||
wlan802_11privfilter8021xWEP
|
||||
};
|
||||
|
||||
/** mv_ms_type */
|
||||
enum mv_ms_type {
|
||||
MVMS_DAT = 0,
|
||||
MVMS_CMD = 1,
|
||||
MVMS_TXDONE = 2,
|
||||
MVMS_EVENT
|
||||
};
|
||||
|
||||
/** WLAN_802_11_NETWORK_INFRASTRUCTURE */
|
||||
enum WLAN_802_11_NETWORK_INFRASTRUCTURE {
|
||||
wlan802_11ibss,
|
||||
wlan802_11infrastructure,
|
||||
wlan802_11autounknown,
|
||||
/*defined as upper bound */
|
||||
wlan802_11infrastructuremax
|
||||
};
|
||||
|
||||
/** WLAN_802_11_AUTHENTICATION_MODE */
|
||||
enum WLAN_802_11_AUTHENTICATION_MODE {
|
||||
wlan802_11authmodeopen = 0x00,
|
||||
wlan802_11authmodeshared = 0x01,
|
||||
wlan802_11authmodenetworkEAP = 0x80,
|
||||
};
|
||||
|
||||
/** WLAN_802_11_WEP_STATUS */
|
||||
enum WLAN_802_11_WEP_STATUS {
|
||||
wlan802_11WEPenabled,
|
||||
wlan802_11WEPdisabled,
|
||||
};
|
||||
|
||||
/** 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
|
||||
#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 /* _WLAN_DEFS_H_ */
|
|
@ -0,0 +1,403 @@
|
|||
/**
|
||||
* This file contains definitions and data structures specific
|
||||
* to Marvell 802.11 NIC. It contains the Device Information
|
||||
* structure wlan_adapter.
|
||||
*/
|
||||
#ifndef _WLAN_DEV_H_
|
||||
#define _WLAN_DEV_H_
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "scan.h"
|
||||
#include "thread.h"
|
||||
|
||||
extern struct ethtool_ops libertas_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 wlan_802_11_security {
|
||||
u8 WPAenabled;
|
||||
u8 WPA2enabled;
|
||||
enum WLAN_802_11_WEP_STATUS WEPstatus;
|
||||
enum WLAN_802_11_AUTHENTICATION_MODE authmode;
|
||||
enum WLAN_802_1X_AUTH_ALG auth1xalg;
|
||||
enum WLAN_802_11_ENCRYPTION_MODE Encryptionmode;
|
||||
};
|
||||
|
||||
/** Current Basic Service Set State Structure */
|
||||
struct current_bss_params {
|
||||
struct bss_descriptor bssdescriptor;
|
||||
/** bssid */
|
||||
u8 bssid[ETH_ALEN];
|
||||
/** ssid */
|
||||
struct WLAN_802_11_SSID ssid;
|
||||
|
||||
/** band */
|
||||
u8 band;
|
||||
/** channel */
|
||||
u8 channel;
|
||||
/** number of rates supported */
|
||||
int numofrates;
|
||||
/** supported rates*/
|
||||
u8 datarates[WLAN_SUPPORTED_RATES];
|
||||
};
|
||||
|
||||
/** sleep_params */
|
||||
struct sleep_params {
|
||||
u16 sp_error;
|
||||
u16 sp_offset;
|
||||
u16 sp_stabletime;
|
||||
u8 sp_calcontrol;
|
||||
u8 sp_extsleepclk;
|
||||
u16 sp_reserved;
|
||||
};
|
||||
|
||||
/** Data structure for the Marvell WLAN device */
|
||||
typedef struct _wlan_dev {
|
||||
/** device name */
|
||||
char name[DEV_NAME_LEN];
|
||||
/** card pointer */
|
||||
void *card;
|
||||
/** IO port */
|
||||
u32 ioport;
|
||||
/** Upload received */
|
||||
u32 upld_rcv;
|
||||
/** Upload type */
|
||||
u32 upld_typ;
|
||||
/** Upload length */
|
||||
u32 upld_len;
|
||||
/** netdev pointer */
|
||||
struct net_device *netdev;
|
||||
/* Upload buffer */
|
||||
u8 upld_buf[WLAN_UPLD_SIZE];
|
||||
/* 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;
|
||||
} wlan_dev_t, *pwlan_dev_t;
|
||||
|
||||
/* Mesh statistics */
|
||||
struct wlan_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 */
|
||||
};
|
||||
|
||||
/** Private structure for the MV device */
|
||||
struct _wlan_private {
|
||||
int open;
|
||||
int mesh_open;
|
||||
int infra_open;
|
||||
|
||||
wlan_adapter *adapter;
|
||||
wlan_dev_t wlan_dev;
|
||||
|
||||
struct net_device_stats stats;
|
||||
struct net_device *mesh_dev ; /* Virtual device */
|
||||
|
||||
struct iw_statistics wstats;
|
||||
struct wlan_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;
|
||||
|
||||
const struct firmware *firmware;
|
||||
struct device *hotplug_device;
|
||||
|
||||
/** thread to service interrupts */
|
||||
struct wlan_thread mainthread;
|
||||
|
||||
struct delayed_work assoc_work;
|
||||
struct workqueue_struct *assoc_thread;
|
||||
};
|
||||
|
||||
/** 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_MODE 3
|
||||
#define ASSOC_FLAG_BSSID 4
|
||||
#define ASSOC_FLAG_WEP_KEYS 5
|
||||
#define ASSOC_FLAG_WEP_TX_KEYIDX 6
|
||||
#define ASSOC_FLAG_WPA_MCAST_KEY 7
|
||||
#define ASSOC_FLAG_WPA_UCAST_KEY 8
|
||||
#define ASSOC_FLAG_SECINFO 9
|
||||
#define ASSOC_FLAG_WPA_IE 10
|
||||
unsigned long flags;
|
||||
|
||||
struct WLAN_802_11_SSID ssid;
|
||||
u8 channel;
|
||||
enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode;
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
/** WEP keys */
|
||||
struct WLAN_802_11_KEY wep_keys[4];
|
||||
u16 wep_tx_keyidx;
|
||||
|
||||
/** WPA keys */
|
||||
struct WLAN_802_11_KEY wpa_mcast_key;
|
||||
struct WLAN_802_11_KEY wpa_unicast_key;
|
||||
|
||||
struct wlan_802_11_security secinfo;
|
||||
|
||||
/** WPA Information Elements*/
|
||||
#define MAX_WPA_IE_LEN 64
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
u8 wpa_ie_len;
|
||||
};
|
||||
|
||||
/** Wlan adapter data structure*/
|
||||
struct _wlan_adapter {
|
||||
/** STATUS variables */
|
||||
u32 fwreleasenumber;
|
||||
u32 fwcapinfo;
|
||||
/* protected with big lock */
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
u8 tmptxbuf[WLAN_UPLD_SIZE];
|
||||
/* protected by hard_start_xmit serialization */
|
||||
|
||||
/** command-related variables */
|
||||
u16 seqnum;
|
||||
/* protected by big lock */
|
||||
|
||||
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;
|
||||
u8 nr_cmd_pending;
|
||||
/* command related variables protected by adapter->driver_lock */
|
||||
|
||||
/** Async and Sync Event variables */
|
||||
u32 intcounter;
|
||||
u32 eventcause;
|
||||
u8 nodename[16]; /* nickname */
|
||||
|
||||
/** spin locks */
|
||||
spinlock_t driver_lock;
|
||||
|
||||
/** Timers */
|
||||
struct timer_list command_timer;
|
||||
|
||||
/* TX queue used in PS mode */
|
||||
spinlock_t txqueue_lock;
|
||||
struct sk_buff *tx_queue_ps[NR_TX_QUEUE];
|
||||
unsigned int tx_queue_idx;
|
||||
|
||||
u8 hisregcpy;
|
||||
|
||||
/** current ssid/bssid related parameters*/
|
||||
struct current_bss_params curbssparams;
|
||||
|
||||
enum WLAN_802_11_NETWORK_INFRASTRUCTURE inframode;
|
||||
|
||||
struct bss_descriptor *pattemptedbssdesc;
|
||||
|
||||
struct WLAN_802_11_SSID previousssid;
|
||||
u8 previousbssid[ETH_ALEN];
|
||||
|
||||
struct bss_descriptor *scantable;
|
||||
u32 numinscantable;
|
||||
|
||||
u8 scantype;
|
||||
u32 scanmode;
|
||||
|
||||
u16 beaconperiod;
|
||||
u8 adhoccreate;
|
||||
|
||||
/** capability Info used in Association, start, join */
|
||||
struct ieeetypes_capinfo capinfo;
|
||||
|
||||
/** 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;
|
||||
/** control G rates */
|
||||
u8 adhoc_grate_enabled;
|
||||
|
||||
u32 txantenna;
|
||||
u32 rxantenna;
|
||||
|
||||
u8 adhocchannel;
|
||||
u32 fragthsd;
|
||||
u32 rtsthsd;
|
||||
|
||||
u32 datarate;
|
||||
u8 is_datarate_auto;
|
||||
|
||||
u16 listeninterval;
|
||||
u16 prescan;
|
||||
u8 txretrycount;
|
||||
|
||||
/** Tx-related variables (for single packet tx) */
|
||||
struct sk_buff *currenttxskb;
|
||||
u16 TxLockFlag;
|
||||
|
||||
/** NIC Operation characteristics */
|
||||
u16 currentpacketfilter;
|
||||
u32 connect_status;
|
||||
u16 regioncode;
|
||||
u16 regiontableindex;
|
||||
u16 txpowerlevel;
|
||||
|
||||
/** POWER MANAGEMENT AND PnP SUPPORT */
|
||||
u8 surpriseremoved;
|
||||
u16 atimwindow;
|
||||
|
||||
u16 psmode; /* Wlan802_11PowermodeCAM=disable
|
||||
Wlan802_11PowermodeMAX_PSP=enable */
|
||||
u16 multipledtim;
|
||||
u32 psstate;
|
||||
u8 needtowakeup;
|
||||
|
||||
struct PS_CMD_ConfirmSleep libertas_ps_confirm_sleep;
|
||||
u16 locallisteninterval;
|
||||
u16 nullpktinterval;
|
||||
|
||||
struct assoc_request * assoc_req;
|
||||
|
||||
/** Encryption parameter */
|
||||
struct wlan_802_11_security secinfo;
|
||||
|
||||
/** WEP keys */
|
||||
struct WLAN_802_11_KEY wep_keys[4];
|
||||
u16 wep_tx_keyidx;
|
||||
|
||||
/** WPA keys */
|
||||
struct WLAN_802_11_KEY wpa_mcast_key;
|
||||
struct WLAN_802_11_KEY wpa_unicast_key;
|
||||
|
||||
/** WPA Information Elements*/
|
||||
#define MAX_WPA_IE_LEN 64
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
u8 wpa_ie_len;
|
||||
|
||||
u16 rxantennamode;
|
||||
u16 txantennamode;
|
||||
|
||||
/** Requested Signal Strength*/
|
||||
u16 bcn_avg_factor;
|
||||
u16 data_avg_factor;
|
||||
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;
|
||||
u16 rxpd_rate;
|
||||
|
||||
u8 radioon;
|
||||
u32 preamble;
|
||||
|
||||
/** Multi bands Parameter*/
|
||||
u8 libertas_supported_rates[G_SUPPORTED_RATES];
|
||||
|
||||
/** Blue Tooth Co-existence Arbitration */
|
||||
|
||||
/** sleep_params */
|
||||
struct sleep_params sp;
|
||||
|
||||
/** 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 wlan_802_11d_domain_reg domainreg;
|
||||
struct parsed_region_chan_11d parsed_region_chan;
|
||||
|
||||
/** FSM variable for 11d support */
|
||||
u32 enable11d;
|
||||
|
||||
/** MISCELLANEOUS */
|
||||
u8 *prdeeprom;
|
||||
struct wlan_offset_value offsetvalue;
|
||||
|
||||
struct cmd_ds_802_11_get_log logmsg;
|
||||
u16 scanprobes;
|
||||
|
||||
u32 pkttxctrl;
|
||||
|
||||
u16 txrate;
|
||||
u32 linkmode;
|
||||
u32 radiomode;
|
||||
u32 debugmode;
|
||||
u8 fw_ready;
|
||||
};
|
||||
|
||||
#endif /* _WLAN_DEV_H_ */
|
|
@ -0,0 +1,184 @@
|
|||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "sbi.h"
|
||||
#include "decl.h"
|
||||
#include "defs.h"
|
||||
#include "dev.h"
|
||||
#include "join.h"
|
||||
#include "wext.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"
|
||||
};
|
||||
|
||||
static void libertas_ethtool_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
wlan_private *priv = (wlan_private *) dev->priv;
|
||||
char fwver[32];
|
||||
|
||||
libertas_get_fwversion(priv->adapter, fwver, sizeof(fwver) - 1);
|
||||
|
||||
strcpy(info->driver, "libertas");
|
||||
strcpy(info->version, libertas_driver_version);
|
||||
strcpy(info->fw_version, fwver);
|
||||
}
|
||||
|
||||
/* All 8388 parts have 16KiB EEPROM size at the time of writing.
|
||||
* In case that changes this needs fixing.
|
||||
*/
|
||||
#define LIBERTAS_EEPROM_LEN 16384
|
||||
|
||||
static int libertas_ethtool_get_eeprom_len(struct net_device *dev)
|
||||
{
|
||||
return LIBERTAS_EEPROM_LEN;
|
||||
}
|
||||
|
||||
static int libertas_ethtool_get_eeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 * bytes)
|
||||
{
|
||||
wlan_private *priv = (wlan_private *) dev->priv;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
struct wlan_ioctl_regrdwr regctrl;
|
||||
char *ptr;
|
||||
int ret;
|
||||
|
||||
regctrl.action = 0;
|
||||
regctrl.offset = eeprom->offset;
|
||||
regctrl.NOB = eeprom->len;
|
||||
|
||||
if (eeprom->offset + eeprom->len > LIBERTAS_EEPROM_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
// mutex_lock(&priv->mutex);
|
||||
|
||||
adapter->prdeeprom =
|
||||
(char *)kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
|
||||
if (!adapter->prdeeprom)
|
||||
return -ENOMEM;
|
||||
memcpy(adapter->prdeeprom, ®ctrl, sizeof(regctrl));
|
||||
|
||||
/* +14 is for action, offset, and NOB in
|
||||
* response */
|
||||
lbs_pr_debug(1, "action:%d offset: %x NOB: %02x\n",
|
||||
regctrl.action, regctrl.offset, regctrl.NOB);
|
||||
|
||||
ret = libertas_prepare_and_send_command(priv,
|
||||
cmd_802_11_eeprom_access,
|
||||
regctrl.action,
|
||||
cmd_option_waitforrsp, 0,
|
||||
®ctrl);
|
||||
|
||||
if (ret) {
|
||||
if (adapter->prdeeprom)
|
||||
kfree(adapter->prdeeprom);
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdelay(10);
|
||||
|
||||
ptr = (char *)adapter->prdeeprom;
|
||||
|
||||
/* skip the command header, but include the "value" u32 variable */
|
||||
ptr = ptr + sizeof(struct wlan_ioctl_regrdwr) - 4;
|
||||
|
||||
/*
|
||||
* Return the result back to the user
|
||||
*/
|
||||
memcpy(bytes, ptr, eeprom->len);
|
||||
|
||||
if (adapter->prdeeprom)
|
||||
kfree(adapter->prdeeprom);
|
||||
// mutex_unlock(&priv->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libertas_ethtool_get_stats(struct net_device * dev,
|
||||
struct ethtool_stats * stats, u64 * data)
|
||||
{
|
||||
wlan_private *priv = dev->priv;
|
||||
|
||||
ENTER();
|
||||
|
||||
stats->cmd = ETHTOOL_GSTATS;
|
||||
BUG_ON(stats->n_stats != MESH_STATS_NUM);
|
||||
|
||||
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;
|
||||
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
static int libertas_ethtool_get_stats_count(struct net_device * dev)
|
||||
{
|
||||
int ret;
|
||||
wlan_private *priv = dev->priv;
|
||||
struct cmd_ds_mesh_access mesh_access;
|
||||
|
||||
ENTER();
|
||||
/* Get Mesh Statistics */
|
||||
ret = libertas_prepare_and_send_command(priv,
|
||||
cmd_mesh_access, cmd_act_mesh_get_stats,
|
||||
cmd_option_waitforrsp, 0, &mesh_access);
|
||||
|
||||
if (ret) {
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->mstats.fwd_drop_rbt = mesh_access.data[0];
|
||||
priv->mstats.fwd_drop_ttl = mesh_access.data[1];
|
||||
priv->mstats.fwd_drop_noroute = mesh_access.data[2];
|
||||
priv->mstats.fwd_drop_nobuf = mesh_access.data[3];
|
||||
priv->mstats.fwd_unicast_cnt = mesh_access.data[4];
|
||||
priv->mstats.fwd_bcast_cnt = mesh_access.data[5];
|
||||
priv->mstats.drop_blind = mesh_access.data[6];
|
||||
|
||||
LEAVE();
|
||||
return MESH_STATS_NUM;
|
||||
}
|
||||
|
||||
static void libertas_ethtool_get_strings (struct net_device * dev,
|
||||
u32 stringset,
|
||||
u8 * s)
|
||||
{
|
||||
int i;
|
||||
|
||||
ENTER();
|
||||
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;
|
||||
}
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
struct ethtool_ops libertas_ethtool_ops = {
|
||||
.get_drvinfo = libertas_ethtool_get_drvinfo,
|
||||
.get_eeprom = libertas_ethtool_get_eeprom,
|
||||
.get_eeprom_len = libertas_ethtool_get_eeprom_len,
|
||||
.get_stats_count = libertas_ethtool_get_stats_count,
|
||||
.get_ethtool_stats = libertas_ethtool_get_stats,
|
||||
.get_strings = libertas_ethtool_get_strings,
|
||||
};
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
/**
|
||||
* This file contains the initialization for FW and HW
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "sbi.h"
|
||||
#include "defs.h"
|
||||
#include "decl.h"
|
||||
#include "dev.h"
|
||||
#include "fw.h"
|
||||
#include "wext.h"
|
||||
#include "if_usb.h"
|
||||
|
||||
char *libertas_fw_name = NULL;
|
||||
module_param_named(fw_name, libertas_fw_name, charp, 0644);
|
||||
|
||||
unsigned int libertas_debug = 0;
|
||||
module_param(libertas_debug, int, 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(u8 *data, u32 totlen)
|
||||
{
|
||||
u8 bincmd, exit;
|
||||
u32 blksize, offset, len;
|
||||
int ret;
|
||||
|
||||
ret = 1;
|
||||
exit = len = 0;
|
||||
|
||||
do {
|
||||
bincmd = *data;
|
||||
blksize = *(u32*)(data + offsetof(struct fwheader, 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("bin file format check FAIL...\n");
|
||||
else
|
||||
lbs_pr_debug(1, "bin file format check PASS...\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function downloads firmware image, gets
|
||||
* HW spec from firmware and set basic parameters to
|
||||
* firmware.
|
||||
*
|
||||
* @param priv A pointer to wlan_private structure
|
||||
* @return 0 or -1
|
||||
*/
|
||||
static int wlan_setup_station_hw(wlan_private * priv)
|
||||
{
|
||||
int ret = -1;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
|
||||
ENTER();
|
||||
|
||||
if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
|
||||
priv->hotplug_device)) < 0) {
|
||||
lbs_pr_err("request_firmware() failed, error code = %#x\n",
|
||||
ret);
|
||||
lbs_pr_err("%s not found in /lib/firmware\n", libertas_fw_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
|
||||
release_firmware(priv->firmware);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = libertas_sbi_prog_firmware(priv);
|
||||
|
||||
release_firmware(priv->firmware);
|
||||
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "Bootloader in invalid state!\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read MAC address from HW
|
||||
*/
|
||||
memset(adapter->current_addr, 0xff, ETH_ALEN);
|
||||
|
||||
ret = libertas_prepare_and_send_command(priv, cmd_get_hw_spec,
|
||||
0, cmd_option_waitforrsp, 0, NULL);
|
||||
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
libertas_set_mac_packet_filter(priv);
|
||||
|
||||
/* Get the supported Data rates */
|
||||
ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate,
|
||||
cmd_act_get_tx_rate,
|
||||
cmd_option_waitforrsp, 0, NULL);
|
||||
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
LEAVE();
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int wlan_allocate_adapter(wlan_private * priv)
|
||||
{
|
||||
u32 ulbufsize;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
|
||||
struct bss_descriptor *ptempscantable;
|
||||
|
||||
/* Allocate buffer to store the BSSID list */
|
||||
ulbufsize = sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST;
|
||||
if (!(ptempscantable = kmalloc(ulbufsize, GFP_KERNEL))) {
|
||||
libertas_free_adapter(priv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
adapter->scantable = ptempscantable;
|
||||
memset(adapter->scantable, 0, ulbufsize);
|
||||
|
||||
/* Allocate the command buffers */
|
||||
libertas_allocate_cmd_buffer(priv);
|
||||
|
||||
memset(&adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep));
|
||||
adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum);
|
||||
adapter->libertas_ps_confirm_sleep.command =
|
||||
cpu_to_le16(cmd_802_11_ps_mode);
|
||||
adapter->libertas_ps_confirm_sleep.size =
|
||||
cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
|
||||
adapter->libertas_ps_confirm_sleep.result = 0;
|
||||
adapter->libertas_ps_confirm_sleep.action =
|
||||
cpu_to_le16(cmd_subcmd_sleep_confirmed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wlan_init_adapter(wlan_private * priv)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int i;
|
||||
|
||||
adapter->scanprobes = 0;
|
||||
|
||||
adapter->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
|
||||
adapter->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
|
||||
|
||||
/* ATIM params */
|
||||
adapter->atimwindow = 0;
|
||||
|
||||
adapter->connect_status = libertas_disconnected;
|
||||
memset(adapter->current_addr, 0xff, ETH_ALEN);
|
||||
|
||||
/* scan type */
|
||||
adapter->scantype = cmd_scan_type_active;
|
||||
|
||||
/* scan mode */
|
||||
adapter->scanmode = cmd_bss_type_any;
|
||||
|
||||
/* 802.11 specific */
|
||||
adapter->secinfo.WEPstatus = wlan802_11WEPdisabled;
|
||||
for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]);
|
||||
i++)
|
||||
memset(&adapter->wep_keys[i], 0, sizeof(struct WLAN_802_11_KEY));
|
||||
adapter->wep_tx_keyidx = 0;
|
||||
adapter->secinfo.WEPstatus = wlan802_11WEPdisabled;
|
||||
adapter->secinfo.authmode = wlan802_11authmodeopen;
|
||||
adapter->secinfo.auth1xalg = WLAN_1X_AUTH_ALG_NONE;
|
||||
adapter->secinfo.Encryptionmode = CIPHER_NONE;
|
||||
adapter->inframode = wlan802_11infrastructure;
|
||||
|
||||
adapter->assoc_req = NULL;
|
||||
|
||||
adapter->numinscantable = 0;
|
||||
adapter->pattemptedbssdesc = NULL;
|
||||
mutex_init(&adapter->lock);
|
||||
|
||||
adapter->prescan = 1;
|
||||
|
||||
memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
|
||||
|
||||
/* PnP and power profile */
|
||||
adapter->surpriseremoved = 0;
|
||||
|
||||
adapter->currentpacketfilter =
|
||||
cmd_act_mac_rx_on | cmd_act_mac_tx_on;
|
||||
|
||||
adapter->radioon = RADIO_ON;
|
||||
adapter->txantenna = RF_ANTENNA_2;
|
||||
adapter->rxantenna = RF_ANTENNA_AUTO;
|
||||
|
||||
adapter->is_datarate_auto = 1;
|
||||
adapter->beaconperiod = MRVDRV_BEACON_INTERVAL;
|
||||
|
||||
// set default value of capinfo.
|
||||
#define SHORT_PREAMBLE_ALLOWED 1
|
||||
memset(&adapter->capinfo, 0, sizeof(adapter->capinfo));
|
||||
adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED;
|
||||
|
||||
adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL;
|
||||
|
||||
adapter->psmode = wlan802_11powermodecam;
|
||||
adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
|
||||
|
||||
adapter->listeninterval = MRVDRV_DEFAULT_LISTEN_INTERVAL;
|
||||
|
||||
adapter->psstate = PS_STATE_FULL_POWER;
|
||||
adapter->needtowakeup = 0;
|
||||
adapter->locallisteninterval = 0; /* default value in firmware will be used */
|
||||
|
||||
adapter->datarate = 0; // Initially indicate the rate as auto
|
||||
|
||||
adapter->adhoc_grate_enabled = 0;
|
||||
|
||||
adapter->intcounter = 0;
|
||||
|
||||
adapter->currenttxskb = NULL;
|
||||
adapter->pkttxctrl = 0;
|
||||
|
||||
memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*));
|
||||
adapter->tx_queue_idx = 0;
|
||||
spin_lock_init(&adapter->txqueue_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void command_timer_fn(unsigned long data);
|
||||
|
||||
int libertas_init_fw(wlan_private * priv)
|
||||
{
|
||||
int ret = -1;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
|
||||
ENTER();
|
||||
|
||||
/* Allocate adapter structure */
|
||||
if ((ret = wlan_allocate_adapter(priv)) != 0)
|
||||
goto done;
|
||||
|
||||
/* init adapter structure */
|
||||
wlan_init_adapter(priv);
|
||||
|
||||
/* init timer etc. */
|
||||
setup_timer(&adapter->command_timer, command_timer_fn,
|
||||
(unsigned long)priv);
|
||||
|
||||
/* download fimrware etc. */
|
||||
if ((ret = wlan_setup_station_hw(priv)) != 0) {
|
||||
del_timer_sync(&adapter->command_timer);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* init 802.11d */
|
||||
libertas_init_11d(priv);
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void libertas_free_adapter(wlan_private * priv)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
|
||||
if (!adapter) {
|
||||
lbs_pr_debug(1, "Why double free adapter?:)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lbs_pr_debug(1, "Free command buffer\n");
|
||||
libertas_free_cmd_buffer(priv);
|
||||
|
||||
lbs_pr_debug(1, "Free commandTimer\n");
|
||||
del_timer(&adapter->command_timer);
|
||||
|
||||
lbs_pr_debug(1, "Free scantable\n");
|
||||
if (adapter->scantable) {
|
||||
kfree(adapter->scantable);
|
||||
adapter->scantable = NULL;
|
||||
}
|
||||
|
||||
lbs_pr_debug(1, "Free adapter\n");
|
||||
|
||||
/* Free the adapter object itself */
|
||||
kfree(adapter);
|
||||
priv->adapter = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function handles the timeout of command sending.
|
||||
* It will re-send the same command again.
|
||||
*/
|
||||
static void command_timer_fn(unsigned long data)
|
||||
{
|
||||
wlan_private *priv = (wlan_private *)data;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
struct cmd_ctrl_node *ptempnode;
|
||||
struct cmd_ds_command *cmd;
|
||||
unsigned long flags;
|
||||
|
||||
ptempnode = adapter->cur_cmd;
|
||||
cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
|
||||
|
||||
lbs_pr_info("command_timer_fn fired (%x)\n", cmd->command);
|
||||
|
||||
if (!adapter->fw_ready)
|
||||
return;
|
||||
|
||||
if (ptempnode == NULL) {
|
||||
lbs_pr_debug(1, "PTempnode Empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&adapter->driver_lock, flags);
|
||||
adapter->cur_cmd = NULL;
|
||||
spin_unlock_irqrestore(&adapter->driver_lock, flags);
|
||||
|
||||
lbs_pr_debug(1, "Re-sending same command as it timeout...!\n");
|
||||
libertas_queue_cmd(adapter, ptempnode, 0);
|
||||
|
||||
wake_up_interruptible(&priv->mainthread.waitq);
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* This header file contains FW interface related definitions.
|
||||
*/
|
||||
#ifndef _WLAN_FW_H_
|
||||
#define _WLAN_FW_H_
|
||||
|
||||
#ifndef DEV_NAME_LEN
|
||||
#define DEV_NAME_LEN 32
|
||||
#endif
|
||||
|
||||
int libertas_init_fw(wlan_private * priv);
|
||||
|
||||
#endif /* _WLAN_FW_H_ */
|
|
@ -0,0 +1,338 @@
|
|||
/**
|
||||
* This file contains definitions of WLAN commands.
|
||||
*/
|
||||
|
||||
#ifndef _HOST_H_
|
||||
#define _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 ID */
|
||||
#define cmd_code_dnld 0x0002
|
||||
#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_pairwise_tsc 0x0036
|
||||
#define cmd_802_11_group_tsc 0x0037
|
||||
#define cmd_802_11_key_material 0x005e
|
||||
|
||||
#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_beacon_stop 0x0049
|
||||
|
||||
#define cmd_802_11_mac_address 0x004D
|
||||
#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_sleep_params 0x0066
|
||||
|
||||
#define cmd_802_11_inactivity_timeout 0x0067
|
||||
|
||||
#define cmd_802_11_tpc_cfg 0x0072
|
||||
#define cmd_802_11_pwr_cfg 0x0073
|
||||
|
||||
#define cmd_802_11_led_gpio_ctrl 0x004e
|
||||
|
||||
#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_ret_bt_access 0x8087
|
||||
|
||||
#define cmd_fwt_access 0x0088
|
||||
#define cmd_ret_fwt_access 0x8088
|
||||
|
||||
#define cmd_mesh_access 0x0090
|
||||
#define cmd_ret_mesh_access 0x8090
|
||||
|
||||
/* 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
|
||||
|
||||
/* command RET code, MSB is set to 1 */
|
||||
#define cmd_ret_hw_spec_info 0x8003
|
||||
#define cmd_ret_eeprom_update 0x8004
|
||||
#define cmd_ret_802_11_reset 0x8005
|
||||
#define cmd_ret_802_11_scan 0x8006
|
||||
#define cmd_ret_802_11_get_log 0x800b
|
||||
#define cmd_ret_mac_control 0x8028
|
||||
#define cmd_ret_mac_multicast_adr 0x8010
|
||||
#define cmd_ret_802_11_authenticate 0x8011
|
||||
#define cmd_ret_802_11_deauthenticate 0x8024
|
||||
#define cmd_ret_802_11_associate 0x8012
|
||||
#define cmd_ret_802_11_reassociate 0x8025
|
||||
#define cmd_ret_802_11_disassociate 0x8026
|
||||
#define cmd_ret_802_11_set_wep 0x8013
|
||||
#define cmd_ret_802_11_stat 0x8014
|
||||
#define cmd_ret_802_3_stat 0x8015
|
||||
#define cmd_ret_802_11_snmp_mib 0x8016
|
||||
#define cmd_ret_mac_reg_map 0x8017
|
||||
#define cmd_ret_bbp_reg_map 0x8018
|
||||
#define cmd_ret_rf_reg_map 0x8023
|
||||
#define cmd_ret_mac_reg_access 0x8019
|
||||
#define cmd_ret_bbp_reg_access 0x801a
|
||||
#define cmd_ret_rf_reg_access 0x801b
|
||||
#define cmd_ret_802_11_radio_control 0x801c
|
||||
#define cmd_ret_802_11_rf_channel 0x801d
|
||||
#define cmd_ret_802_11_rssi 0x801f
|
||||
#define cmd_ret_802_11_rf_tx_power 0x801e
|
||||
#define cmd_ret_802_11_rf_antenna 0x8020
|
||||
#define cmd_ret_802_11_ps_mode 0x8021
|
||||
#define cmd_ret_802_11_data_rate 0x8022
|
||||
|
||||
#define cmd_ret_802_11_ad_hoc_start 0x802B
|
||||
#define cmd_ret_802_11_ad_hoc_join 0x802C
|
||||
|
||||
#define cmd_ret_802_11_query_tkip_reply_cntrs 0x802e
|
||||
#define cmd_ret_802_11_enable_rsn 0x802f
|
||||
#define cmd_ret_802_11_pairwise_tsc 0x8036
|
||||
#define cmd_ret_802_11_group_tsc 0x8037
|
||||
#define cmd_ret_802_11_key_material 0x805e
|
||||
|
||||
#define cmd_enable_rsn 0x0001
|
||||
#define cmd_disable_rsn 0x0000
|
||||
|
||||
#define cmd_act_set 0x0001
|
||||
#define cmd_act_get 0x0000
|
||||
|
||||
#define cmd_act_get_AES (cmd_act_get + 2)
|
||||
#define cmd_act_set_AES (cmd_act_set + 2)
|
||||
#define cmd_act_remove_aes (cmd_act_set + 3)
|
||||
|
||||
#define cmd_ret_802_11_set_afc 0x803c
|
||||
#define cmd_ret_802_11_get_afc 0x803d
|
||||
|
||||
#define cmd_ret_802_11_ad_hoc_stop 0x8040
|
||||
|
||||
#define cmd_ret_802_11_beacon_stop 0x8049
|
||||
|
||||
#define cmd_ret_802_11_mac_address 0x804D
|
||||
#define cmd_ret_802_11_eeprom_access 0x8059
|
||||
|
||||
#define cmd_ret_802_11_band_config 0x8058
|
||||
|
||||
#define cmd_ret_802_11_sleep_params 0x8066
|
||||
|
||||
#define cmd_ret_802_11_inactivity_timeout 0x8067
|
||||
|
||||
#define cmd_ret_802_11d_domain_info (0x8000 | \
|
||||
cmd_802_11d_domain_info)
|
||||
|
||||
#define cmd_ret_802_11_tpc_cfg (cmd_802_11_tpc_cfg | 0x8000)
|
||||
#define cmd_ret_802_11_pwr_cfg (cmd_802_11_pwr_cfg | 0x8000)
|
||||
|
||||
#define cmd_ret_802_11_led_gpio_ctrl 0x804e
|
||||
|
||||
#define cmd_ret_802_11_subscribe_event (cmd_802_11_subscribe_event | 0x8000)
|
||||
|
||||
#define cmd_ret_802_11_rate_adapt_rateset (cmd_802_11_rate_adapt_rateset | 0x8000)
|
||||
|
||||
#define cmd_rte_802_11_tx_rate_query (cmd_802_11_tx_rate_query | 0x8000)
|
||||
|
||||
#define cmd_ret_get_tsf 0x8080
|
||||
|
||||
/* 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 0x0001
|
||||
#define cmd_type_wep_104_bit 0x0002
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
/* 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
|
||||
};
|
||||
|
||||
/* 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_mpp,
|
||||
cmd_act_mesh_set_mpp,
|
||||
};
|
||||
|
||||
/** Card Event definition */
|
||||
#define MACREG_INT_CODE_TX_PPA_FREE 0x00000000
|
||||
#define MACREG_INT_CODE_TX_DMA_DONE 0x00000001
|
||||
#define MACREG_INT_CODE_LINK_LOSE_W_SCAN 0x00000002
|
||||
#define MACREG_INT_CODE_LINK_LOSE_NO_SCAN 0x00000003
|
||||
#define MACREG_INT_CODE_LINK_SENSED 0x00000004
|
||||
#define MACREG_INT_CODE_CMD_FINISHED 0x00000005
|
||||
#define MACREG_INT_CODE_MIB_CHANGED 0x00000006
|
||||
#define MACREG_INT_CODE_INIT_DONE 0x00000007
|
||||
#define MACREG_INT_CODE_DEAUTHENTICATED 0x00000008
|
||||
#define MACREG_INT_CODE_DISASSOCIATED 0x00000009
|
||||
#define MACREG_INT_CODE_PS_AWAKE 0x0000000a
|
||||
#define MACREG_INT_CODE_PS_SLEEP 0x0000000b
|
||||
#define MACREG_INT_CODE_MIC_ERR_MULTICAST 0x0000000d
|
||||
#define MACREG_INT_CODE_MIC_ERR_UNICAST 0x0000000e
|
||||
#define MACREG_INT_CODE_WM_AWAKE 0x0000000f
|
||||
#define MACREG_INT_CODE_ADHOC_BCN_LOST 0x00000011
|
||||
#define MACREG_INT_CODE_RSSI_LOW 0x00000019
|
||||
#define MACREG_INT_CODE_SNR_LOW 0x0000001a
|
||||
#define MACREG_INT_CODE_MAX_FAIL 0x0000001b
|
||||
#define MACREG_INT_CODE_RSSI_HIGH 0x0000001c
|
||||
#define MACREG_INT_CODE_SNR_HIGH 0x0000001d
|
||||
|
||||
#endif /* _HOST_H_ */
|
|
@ -0,0 +1,693 @@
|
|||
/*
|
||||
* This file contains the function prototypes, data structure
|
||||
* and defines for all the host/station commands
|
||||
*/
|
||||
#ifndef __HOSTCMD__H
|
||||
#define __HOSTCMD__H
|
||||
|
||||
#include <linux/wireless.h>
|
||||
#include "11d.h"
|
||||
#include "types.h"
|
||||
|
||||
/* 802.11-related definitions */
|
||||
|
||||
/* TxPD descriptor */
|
||||
struct txpd {
|
||||
/* Current Tx packet status */
|
||||
u32 tx_status;
|
||||
/* Tx control */
|
||||
u32 tx_control;
|
||||
u32 tx_packet_location;
|
||||
/* Tx packet length */
|
||||
u16 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 */
|
||||
u16 status;
|
||||
|
||||
/* SNR */
|
||||
u8 snr;
|
||||
|
||||
/* Tx control */
|
||||
u8 rx_control;
|
||||
|
||||
/* Pkt length */
|
||||
u16 pkt_len;
|
||||
|
||||
/* Noise Floor */
|
||||
u8 nf;
|
||||
|
||||
/* Rx Packet Rate */
|
||||
u8 rx_rate;
|
||||
|
||||
/* Pkt addr */
|
||||
u32 pkt_ptr;
|
||||
|
||||
/* Next Rx RxPD addr */
|
||||
u32 next_rxpd_ptr;
|
||||
|
||||
/* Pkt Priority */
|
||||
u8 priority;
|
||||
u8 reserved[3];
|
||||
};
|
||||
|
||||
struct cmd_ctrl_node {
|
||||
/* CMD link list */
|
||||
struct list_head list;
|
||||
u32 status;
|
||||
/* CMD ID */
|
||||
u32 cmd_oid;
|
||||
/*CMD wait option: wait for finish or no wait */
|
||||
u16 wait_option;
|
||||
/* command parameter */
|
||||
void *pdata_buf;
|
||||
/*command data */
|
||||
u8 *bufvirtualaddr;
|
||||
u16 cmdflags;
|
||||
/* wait queue */
|
||||
u16 cmdwaitqwoken;
|
||||
wait_queue_head_t cmdwait_q;
|
||||
};
|
||||
|
||||
/* WLAN_802_11_KEY
|
||||
*
|
||||
* Generic structure to hold all key types. key type (WEP40, WEP104, TKIP, AES)
|
||||
* is determined from the keylength field.
|
||||
*/
|
||||
struct WLAN_802_11_KEY {
|
||||
u32 len;
|
||||
u32 flags; /* KEY_INFO_* from wlan_defs.h */
|
||||
u8 key[MRVL_MAX_KEY_WPA_KEY_LENGTH];
|
||||
u16 type; /* KEY_TYPE_* from wlan_defs.h */
|
||||
};
|
||||
|
||||
struct IE_WPA {
|
||||
u8 elementid;
|
||||
u8 len;
|
||||
u8 oui[4];
|
||||
u16 version;
|
||||
};
|
||||
|
||||
struct WLAN_802_11_SSID {
|
||||
/* SSID length */
|
||||
u32 ssidlength;
|
||||
|
||||
/* SSID information field */
|
||||
u8 ssid[IW_ESSID_MAX_SIZE];
|
||||
};
|
||||
|
||||
struct WPA_SUPPLICANT {
|
||||
u8 wpa_ie[256];
|
||||
u8 wpa_ie_len;
|
||||
};
|
||||
|
||||
/* wlan_offset_value */
|
||||
struct wlan_offset_value {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
struct WLAN_802_11_FIXED_IEs {
|
||||
u8 timestamp[8];
|
||||
u16 beaconinterval;
|
||||
u16 capabilities;
|
||||
};
|
||||
|
||||
struct WLAN_802_11_VARIABLE_IEs {
|
||||
u8 elementid;
|
||||
u8 length;
|
||||
u8 data[1];
|
||||
};
|
||||
|
||||
/* Define general data structure */
|
||||
/* cmd_DS_GEN */
|
||||
struct cmd_ds_gen {
|
||||
u16 command;
|
||||
u16 size;
|
||||
u16 seqnum;
|
||||
u16 result;
|
||||
};
|
||||
|
||||
#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 {
|
||||
/* HW Interface version number */
|
||||
u16 hwifversion;
|
||||
/* HW version number */
|
||||
u16 version;
|
||||
/* Max number of TxPD FW can handle */
|
||||
u16 nr_txpd;
|
||||
/* Max no of Multicast address */
|
||||
u16 nr_mcast_adr;
|
||||
/* MAC address */
|
||||
u8 permanentaddr[6];
|
||||
|
||||
/* region Code */
|
||||
u16 regioncode;
|
||||
|
||||
/* Number of antenna used */
|
||||
u16 nr_antenna;
|
||||
|
||||
/* FW release number, example 0x1234=1.2.3.4 */
|
||||
u32 fwreleasenumber;
|
||||
|
||||
/* Base Address of TxPD queue */
|
||||
u32 wcb_base;
|
||||
/* Read Pointer of RxPd queue */
|
||||
u32 rxpd_rdptr;
|
||||
|
||||
/* Write Pointer of RxPd queue */
|
||||
u32 rxpd_wrptr;
|
||||
|
||||
/*FW/HW capability */
|
||||
u32 fwcapinfo;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_reset {
|
||||
u16 action;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_subscribe_event {
|
||||
u16 action;
|
||||
u16 events;
|
||||
};
|
||||
|
||||
/*
|
||||
* This scan handle Country Information IE(802.11d compliant)
|
||||
* Define data structure for cmd_802_11_scan
|
||||
*/
|
||||
struct cmd_ds_802_11_scan {
|
||||
u8 bsstype;
|
||||
u8 BSSID[ETH_ALEN];
|
||||
u8 tlvbuffer[1];
|
||||
#if 0
|
||||
mrvlietypes_ssidparamset_t ssidParamSet;
|
||||
mrvlietypes_chanlistparamset_t ChanListParamSet;
|
||||
mrvlietypes_ratesparamset_t OpRateSet;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_scan_rsp {
|
||||
u16 bssdescriptsize;
|
||||
u8 nr_sets;
|
||||
u8 bssdesc_and_tlvbuffer[1];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_get_log {
|
||||
u32 mcasttxframe;
|
||||
u32 failed;
|
||||
u32 retry;
|
||||
u32 multiretry;
|
||||
u32 framedup;
|
||||
u32 rtssuccess;
|
||||
u32 rtsfailure;
|
||||
u32 ackfailure;
|
||||
u32 rxfrag;
|
||||
u32 mcastrxframe;
|
||||
u32 fcserror;
|
||||
u32 txframe;
|
||||
u32 wepundecryptable;
|
||||
};
|
||||
|
||||
struct cmd_ds_mac_control {
|
||||
u16 action;
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
struct cmd_ds_mac_multicast_adr {
|
||||
u16 action;
|
||||
u16 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];
|
||||
u16 reasoncode;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_associate {
|
||||
u8 peerstaaddr[6];
|
||||
struct ieeetypes_capinfo capinfo;
|
||||
u16 listeninterval;
|
||||
u16 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];
|
||||
u16 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 {
|
||||
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
|
||||
u16 action;
|
||||
|
||||
/* key Index selected for Tx */
|
||||
u16 keyindex;
|
||||
|
||||
/* 40, 128bit or TXWEP */
|
||||
u8 keytype[4];
|
||||
u8 keymaterial[4][16];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_3_get_stat {
|
||||
u32 xmitok;
|
||||
u32 rcvok;
|
||||
u32 xmiterror;
|
||||
u32 rcverror;
|
||||
u32 rcvnobuffer;
|
||||
u32 rcvcrcerror;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_get_stat {
|
||||
u32 txfragmentcnt;
|
||||
u32 mcasttxframecnt;
|
||||
u32 failedcnt;
|
||||
u32 retrycnt;
|
||||
u32 Multipleretrycnt;
|
||||
u32 rtssuccesscnt;
|
||||
u32 rtsfailurecnt;
|
||||
u32 ackfailurecnt;
|
||||
u32 frameduplicatecnt;
|
||||
u32 rxfragmentcnt;
|
||||
u32 mcastrxframecnt;
|
||||
u32 fcserrorcnt;
|
||||
u32 bcasttxframecnt;
|
||||
u32 bcastrxframecnt;
|
||||
u32 txbeacon;
|
||||
u32 rxbeacon;
|
||||
u32 wepundecryptable;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_snmp_mib {
|
||||
u16 querytype;
|
||||
u16 oid;
|
||||
u16 bufsize;
|
||||
u8 value[128];
|
||||
};
|
||||
|
||||
struct cmd_ds_mac_reg_map {
|
||||
u16 buffersize;
|
||||
u8 regmap[128];
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
struct cmd_ds_bbp_reg_map {
|
||||
u16 buffersize;
|
||||
u8 regmap[128];
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
struct cmd_ds_rf_reg_map {
|
||||
u16 buffersize;
|
||||
u8 regmap[64];
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
struct cmd_ds_mac_reg_access {
|
||||
u16 action;
|
||||
u16 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
struct cmd_ds_bbp_reg_access {
|
||||
u16 action;
|
||||
u16 offset;
|
||||
u8 value;
|
||||
u8 reserved[3];
|
||||
};
|
||||
|
||||
struct cmd_ds_rf_reg_access {
|
||||
u16 action;
|
||||
u16 offset;
|
||||
u8 value;
|
||||
u8 reserved[3];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_radio_control {
|
||||
u16 action;
|
||||
u16 control;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_sleep_params {
|
||||
/* ACT_GET/ACT_SET */
|
||||
u16 action;
|
||||
|
||||
/* Sleep clock error in ppm */
|
||||
u16 error;
|
||||
|
||||
/* Wakeup offset in usec */
|
||||
u16 offset;
|
||||
|
||||
/* Clock stabilization time in usec */
|
||||
u16 stabletime;
|
||||
|
||||
/* control periodic calibration */
|
||||
u8 calcontrol;
|
||||
|
||||
/* control the use of external sleep clock */
|
||||
u8 externalsleepclk;
|
||||
|
||||
/* reserved field, should be set to zero */
|
||||
u16 reserved;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_inactivity_timeout {
|
||||
/* ACT_GET/ACT_SET */
|
||||
u16 action;
|
||||
|
||||
/* Inactivity timeout in msec */
|
||||
u16 timeout;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rf_channel {
|
||||
u16 action;
|
||||
u16 currentchannel;
|
||||
u16 rftype;
|
||||
u16 reserved;
|
||||
u8 channellist[32];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rssi {
|
||||
/* weighting factor */
|
||||
u16 N;
|
||||
|
||||
u16 reserved_0;
|
||||
u16 reserved_1;
|
||||
u16 reserved_2;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rssi_rsp {
|
||||
u16 SNR;
|
||||
u16 noisefloor;
|
||||
u16 avgSNR;
|
||||
u16 avgnoisefloor;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_mac_address {
|
||||
u16 action;
|
||||
u8 macadd[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rf_tx_power {
|
||||
u16 action;
|
||||
u16 currentlevel;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rf_antenna {
|
||||
u16 action;
|
||||
|
||||
/* Number of antennas or 0xffff(diversity) */
|
||||
u16 antennamode;
|
||||
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_ps_mode {
|
||||
u16 action;
|
||||
u16 nullpktinterval;
|
||||
u16 multipledtim;
|
||||
u16 reserved;
|
||||
u16 locallisteninterval;
|
||||
};
|
||||
|
||||
struct PS_CMD_ConfirmSleep {
|
||||
u16 command;
|
||||
u16 size;
|
||||
u16 seqnum;
|
||||
u16 result;
|
||||
|
||||
u16 action;
|
||||
u16 reserved1;
|
||||
u16 multipledtim;
|
||||
u16 reserved;
|
||||
u16 locallisteninterval;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_data_rate {
|
||||
u16 action;
|
||||
u16 reserverd;
|
||||
u8 datarate[G_SUPPORTED_RATES];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rate_adapt_rateset {
|
||||
u16 action;
|
||||
u16 enablehwauto;
|
||||
u16 bitmap;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_start {
|
||||
u8 SSID[IW_ESSID_MAX_SIZE];
|
||||
u8 bsstype;
|
||||
u16 beaconperiod;
|
||||
u8 dtimperiod;
|
||||
union IEEEtypes_ssparamset ssparamset;
|
||||
union ieeetypes_phyparamset phyparamset;
|
||||
u16 probedelay;
|
||||
struct ieeetypes_capinfo cap;
|
||||
u8 datarate[G_SUPPORTED_RATES];
|
||||
u8 tlv_memory_size_pad[100];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct adhoc_bssdesc {
|
||||
u8 BSSID[6];
|
||||
u8 SSID[32];
|
||||
u8 bsstype;
|
||||
u16 beaconperiod;
|
||||
u8 dtimperiod;
|
||||
u8 timestamp[8];
|
||||
u8 localtime[8];
|
||||
union ieeetypes_phyparamset phyparamset;
|
||||
union IEEEtypes_ssparamset ssparamset;
|
||||
struct ieeetypes_capinfo cap;
|
||||
u8 datarates[G_SUPPORTED_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 bssdescriptor;
|
||||
u16 failtimeout;
|
||||
u16 probedelay;
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_enable_rsn {
|
||||
u16 action;
|
||||
u16 enable;
|
||||
};
|
||||
|
||||
struct MrvlIEtype_keyParamSet {
|
||||
/* type ID */
|
||||
u16 type;
|
||||
|
||||
/* length of Payload */
|
||||
u16 length;
|
||||
|
||||
/* type of key: WEP=0, TKIP=1, AES=2 */
|
||||
u16 keytypeid;
|
||||
|
||||
/* key control Info specific to a keytypeid */
|
||||
u16 keyinfo;
|
||||
|
||||
/* length of key */
|
||||
u16 keylen;
|
||||
|
||||
/* key material of size keylen */
|
||||
u8 key[32];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_key_material {
|
||||
u16 action;
|
||||
struct MrvlIEtype_keyParamSet keyParamSet[2];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_eeprom_access {
|
||||
u16 action;
|
||||
|
||||
/* multiple 4 */
|
||||
u16 offset;
|
||||
u16 bytecount;
|
||||
u8 value;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_tpc_cfg {
|
||||
u16 action;
|
||||
u8 enable;
|
||||
s8 P0;
|
||||
s8 P1;
|
||||
s8 P2;
|
||||
u8 usesnr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_led_ctrl {
|
||||
u16 action;
|
||||
u16 numled;
|
||||
u8 data[256];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_pwr_cfg {
|
||||
u16 action;
|
||||
u8 enable;
|
||||
s8 PA_P0;
|
||||
s8 PA_P1;
|
||||
s8 PA_P2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_afc {
|
||||
u16 afc_auto;
|
||||
union {
|
||||
struct {
|
||||
u16 threshold;
|
||||
u16 period;
|
||||
};
|
||||
struct {
|
||||
s16 timing_offset;
|
||||
s16 carrier_offset;
|
||||
};
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_tx_rate_query {
|
||||
u16 txrate;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_get_tsf {
|
||||
__le64 tsfvalue;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_bt_access {
|
||||
u16 action;
|
||||
u32 id;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_fwt_access {
|
||||
u16 action;
|
||||
u32 id;
|
||||
u8 da[ETH_ALEN];
|
||||
u8 dir;
|
||||
u8 ra[ETH_ALEN];
|
||||
u32 ssn;
|
||||
u32 dsn;
|
||||
u32 metric;
|
||||
u8 hopcount;
|
||||
u8 ttl;
|
||||
u32 expiration;
|
||||
u8 sleepmode;
|
||||
u32 snr;
|
||||
u32 references;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define MESH_STATS_NUM 7
|
||||
struct cmd_ds_mesh_access {
|
||||
u16 action;
|
||||
u32 data[MESH_STATS_NUM + 1]; /* last position reserved */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_command {
|
||||
/* command header */
|
||||
u16 command;
|
||||
u16 size;
|
||||
u16 seqnum;
|
||||
u16 result;
|
||||
|
||||
/* command Body */
|
||||
union {
|
||||
struct cmd_ds_get_hw_spec hwspec;
|
||||
struct cmd_ds_802_11_ps_mode psmode;
|
||||
struct cmd_ds_802_11_scan scan;
|
||||
struct cmd_ds_802_11_scan_rsp scanresp;
|
||||
struct cmd_ds_mac_control macctrl;
|
||||
struct cmd_ds_802_11_associate associate;
|
||||
struct cmd_ds_802_11_deauthenticate deauth;
|
||||
struct cmd_ds_802_11_set_wep wep;
|
||||
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_get_log glog;
|
||||
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_data_rate drate;
|
||||
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_radio_control radio;
|
||||
struct cmd_ds_802_11_rf_channel rfchannel;
|
||||
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_802_11_mac_address macadd;
|
||||
struct cmd_ds_802_11_enable_rsn enbrsn;
|
||||
struct cmd_ds_802_11_key_material keymaterial;
|
||||
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_11_eeprom_access rdeeprom;
|
||||
|
||||
struct cmd_ds_802_11d_domain_info domaininfo;
|
||||
struct cmd_ds_802_11d_domain_info domaininforesp;
|
||||
|
||||
struct cmd_ds_802_11_sleep_params sleep_params;
|
||||
struct cmd_ds_802_11_inactivity_timeout inactivity_timeout;
|
||||
struct cmd_ds_802_11_tpc_cfg tpccfg;
|
||||
struct cmd_ds_802_11_pwr_cfg pwrcfg;
|
||||
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_mesh_access mesh;
|
||||
struct cmd_ds_get_tsf gettsf;
|
||||
struct cmd_ds_802_11_subscribe_event subscribe_event;
|
||||
} params;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* This file contains functions used in USB Boot command
|
||||
* and Boot2/FW update
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "dev.h"
|
||||
#include "if_usb.h"
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
|
||||
{
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
struct bootcmdstr sbootcmd;
|
||||
int i;
|
||||
|
||||
/* Prepare command */
|
||||
sbootcmd.u32magicnumber = BOOT_CMD_MAGIC_NUMBER;
|
||||
sbootcmd.u8cmd_tag = ivalue;
|
||||
for (i=0; i<11; i++)
|
||||
sbootcmd.au8dumy[i]=0x00;
|
||||
memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr));
|
||||
|
||||
/* Issue command */
|
||||
usb_tx_block(priv, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,952 @@
|
|||
/**
|
||||
* This file contains functions used in USB interface module.
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "sbi.h"
|
||||
#include "decl.h"
|
||||
#include "defs.h"
|
||||
#include "dev.h"
|
||||
#include "if_usb.h"
|
||||
|
||||
#define MESSAGE_HEADER_LEN 4
|
||||
|
||||
static const char usbdriver_name[] = "usb8xxx";
|
||||
|
||||
static struct usb_device_id if_usb_table[] = {
|
||||
/* Enter the device signature inside */
|
||||
{
|
||||
USB_DEVICE(USB8388_VID_1, USB8388_PID_1),
|
||||
},
|
||||
{
|
||||
USB_DEVICE(USB8388_VID_2, USB8388_PID_2),
|
||||
},
|
||||
{} /* 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);
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
wlan_private *priv = (wlan_private *) (urb->context);
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
struct net_device *dev = priv->wlan_dev.netdev;
|
||||
|
||||
/* handle the transmission complete validations */
|
||||
|
||||
if (urb->status != 0) {
|
||||
/* print the failure status number for debug */
|
||||
lbs_pr_info("URB in failure status\n");
|
||||
} else {
|
||||
lbs_dev_dbg(2, &urb->dev->dev, "URB status is successfull\n");
|
||||
lbs_dev_dbg(2, &urb->dev->dev, "Actual length transmitted %d\n",
|
||||
urb->actual_length);
|
||||
priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
|
||||
/* Wake main thread if commands are pending */
|
||||
if (!adapter->cur_cmd)
|
||||
wake_up_interruptible(&priv->mainthread.waitq);
|
||||
if ((adapter->connect_status == libertas_connected))
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief free tx/rx urb, skb and rx buffer
|
||||
* @param cardp pointer usb_card_rec
|
||||
* @return N/A
|
||||
*/
|
||||
void if_usb_free(struct usb_card_rec *cardp)
|
||||
{
|
||||
ENTER();
|
||||
|
||||
/* 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->bulk_out_buffer);
|
||||
cardp->bulk_out_buffer = NULL;
|
||||
|
||||
LEAVE();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
wlan_private *pwlanpriv;
|
||||
struct usb_card_rec *usb_cardp;
|
||||
int i;
|
||||
|
||||
udev = interface_to_usbdev(intf);
|
||||
|
||||
usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
|
||||
if (!usb_cardp) {
|
||||
lbs_pr_err("Out of memory allocating private data.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
usb_cardp->udev = udev;
|
||||
iface_desc = intf->cur_altsetting;
|
||||
|
||||
lbs_dev_dbg(1, &udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
|
||||
" bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
|
||||
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 ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_BULK)) {
|
||||
/* we found a bulk in endpoint */
|
||||
lbs_dev_dbg(1, &udev->dev, "Bulk in size is %d\n",
|
||||
endpoint->wMaxPacketSize);
|
||||
if (!
|
||||
(usb_cardp->rx_urb =
|
||||
usb_alloc_urb(0, GFP_KERNEL))) {
|
||||
lbs_dev_dbg(1, &udev->dev,
|
||||
"Rx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
usb_cardp->rx_urb_recall = 0;
|
||||
|
||||
usb_cardp->bulk_in_size =
|
||||
endpoint->wMaxPacketSize;
|
||||
usb_cardp->bulk_in_endpointAddr =
|
||||
(endpoint->
|
||||
bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
|
||||
lbs_dev_dbg(1, &udev->dev, "in_endpoint = %d\n",
|
||||
endpoint->bEndpointAddress);
|
||||
}
|
||||
|
||||
if (((endpoint->
|
||||
bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
|
||||
USB_DIR_OUT)
|
||||
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_BULK)) {
|
||||
/* We found bulk out endpoint */
|
||||
if (!
|
||||
(usb_cardp->tx_urb =
|
||||
usb_alloc_urb(0, GFP_KERNEL))) {
|
||||
lbs_dev_dbg(1,&udev->dev,
|
||||
"Tx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
usb_cardp->bulk_out_size =
|
||||
endpoint->wMaxPacketSize;
|
||||
lbs_dev_dbg(1, &udev->dev,
|
||||
"Bulk out size is %d\n",
|
||||
endpoint->wMaxPacketSize);
|
||||
usb_cardp->bulk_out_endpointAddr =
|
||||
endpoint->bEndpointAddress;
|
||||
lbs_dev_dbg(1, &udev->dev, "out_endpoint = %d\n",
|
||||
endpoint->bEndpointAddress);
|
||||
usb_cardp->bulk_out_buffer =
|
||||
kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!usb_cardp->bulk_out_buffer) {
|
||||
lbs_dev_dbg(1, &udev->dev,
|
||||
"Could not allocate buffer\n");
|
||||
goto dealloc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* At this point wlan_add_card() will be called. Don't worry
|
||||
* about keeping pwlanpriv around since it will be set on our
|
||||
* usb device data in -> add() -> libertas_sbi_register_dev().
|
||||
*/
|
||||
if (!(pwlanpriv = wlan_add_card(usb_cardp)))
|
||||
goto dealloc;
|
||||
|
||||
usb_get_dev(udev);
|
||||
usb_set_intfdata(intf, usb_cardp);
|
||||
|
||||
/*
|
||||
* return card structure, which can be got back in the
|
||||
* diconnect function as the ptr
|
||||
* argument.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
dealloc:
|
||||
if_usb_free(usb_cardp);
|
||||
|
||||
error:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief free resource and cleanup
|
||||
* @param udev pointer to usb_device
|
||||
* @param ptr pointer to usb_cardp
|
||||
* @return N/A
|
||||
*/
|
||||
static void if_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_card_rec *cardp = usb_get_intfdata(intf);
|
||||
wlan_private *priv = (wlan_private *) cardp->priv;
|
||||
wlan_adapter *adapter = NULL;
|
||||
|
||||
adapter = priv->adapter;
|
||||
|
||||
/*
|
||||
* Update Surprise removed to TRUE
|
||||
*/
|
||||
adapter->surpriseremoved = 1;
|
||||
|
||||
/* card is removed and we can call wlan_remove_card */
|
||||
lbs_dev_dbg(1, &cardp->udev->dev, "call remove card\n");
|
||||
wlan_remove_card(cardp);
|
||||
|
||||
/* Unlink and free urb */
|
||||
if_usb_free(cardp);
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(intf));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function download FW
|
||||
* @param priv pointer to wlan_private
|
||||
* @return 0
|
||||
*/
|
||||
static int if_prog_firmware(wlan_private * priv)
|
||||
{
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
struct FWData *fwdata;
|
||||
struct fwheader *fwheader;
|
||||
u8 *firmware = priv->firmware->data;
|
||||
|
||||
fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
|
||||
|
||||
if (!fwdata)
|
||||
return -1;
|
||||
|
||||
fwheader = &fwdata->fwheader;
|
||||
|
||||
if (!cardp->CRC_OK) {
|
||||
cardp->totalbytes = cardp->fwlastblksent;
|
||||
cardp->fwseqnum = cardp->lastseqnum - 1;
|
||||
}
|
||||
|
||||
lbs_dev_dbg(2, &cardp->udev->dev, "totalbytes = %d\n",
|
||||
cardp->totalbytes);
|
||||
|
||||
memcpy(fwheader, &firmware[cardp->totalbytes],
|
||||
sizeof(struct fwheader));
|
||||
|
||||
cardp->fwlastblksent = cardp->totalbytes;
|
||||
cardp->totalbytes += sizeof(struct fwheader);
|
||||
|
||||
lbs_dev_dbg(2, &cardp->udev->dev,"Copy Data\n");
|
||||
memcpy(fwdata->data, &firmware[cardp->totalbytes],
|
||||
fwdata->fwheader.datalength);
|
||||
|
||||
lbs_dev_dbg(2, &cardp->udev->dev,
|
||||
"Data length = %d\n", fwdata->fwheader.datalength);
|
||||
|
||||
cardp->fwseqnum = cardp->fwseqnum + 1;
|
||||
|
||||
fwdata->seqnum = cardp->fwseqnum;
|
||||
cardp->lastseqnum = fwdata->seqnum;
|
||||
cardp->totalbytes += fwdata->fwheader.datalength;
|
||||
|
||||
if (fwheader->dnldcmd == FW_HAS_DATA_TO_RECV) {
|
||||
lbs_dev_dbg(2, &cardp->udev->dev, "There is data to follow\n");
|
||||
lbs_dev_dbg(2, &cardp->udev->dev,
|
||||
"seqnum = %d totalbytes = %d\n", cardp->fwseqnum,
|
||||
cardp->totalbytes);
|
||||
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
|
||||
usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
||||
|
||||
} else if (fwdata->fwheader.dnldcmd == FW_HAS_LAST_BLOCK) {
|
||||
lbs_dev_dbg(2, &cardp->udev->dev,
|
||||
"Host has finished FW downloading\n");
|
||||
lbs_dev_dbg(2, &cardp->udev->dev,
|
||||
"Donwloading FW JUMP BLOCK\n");
|
||||
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
|
||||
usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
||||
cardp->fwfinalblk = 1;
|
||||
}
|
||||
|
||||
lbs_dev_dbg(2, &cardp->udev->dev,
|
||||
"The firmware download is done size is %d\n",
|
||||
cardp->totalbytes);
|
||||
|
||||
kfree(fwdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libertas_do_reset(wlan_private *priv)
|
||||
{
|
||||
int ret;
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
|
||||
ret = usb_reset_device(cardp->udev);
|
||||
if (!ret) {
|
||||
msleep(10);
|
||||
reset_device(priv);
|
||||
msleep(10);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function transfer the data to the device.
|
||||
* @param priv pointer to wlan_private
|
||||
* @param payload pointer to payload data
|
||||
* @param nb data length
|
||||
* @return 0 or -1
|
||||
*/
|
||||
int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
|
||||
{
|
||||
/* pointer to card structure */
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
int ret = -1;
|
||||
|
||||
/* check if device is removed */
|
||||
if (priv->adapter->surpriseremoved) {
|
||||
lbs_dev_dbg(1, &cardp->udev->dev, "Device removed\n");
|
||||
goto tx_ret;
|
||||
}
|
||||
|
||||
usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
|
||||
usb_sndbulkpipe(cardp->udev,
|
||||
cardp->bulk_out_endpointAddr),
|
||||
payload, nb, if_usb_write_bulk_callback, priv);
|
||||
|
||||
cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
|
||||
/* transfer failed */
|
||||
lbs_dev_dbg(1, &cardp->udev->dev, "usb_submit_urb failed\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
lbs_dev_dbg(2, &cardp->udev->dev, "usb_submit_urb success\n");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
tx_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __if_usb_submit_rx_urb(wlan_private * priv,
|
||||
void (*callbackfn)
|
||||
(struct urb *urb))
|
||||
{
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
struct sk_buff *skb;
|
||||
struct read_cb_info *rinfo = &cardp->rinfo;
|
||||
int ret = -1;
|
||||
|
||||
if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
|
||||
lbs_pr_err("No free skb\n");
|
||||
goto rx_ret;
|
||||
}
|
||||
|
||||
rinfo->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->bulk_in_endpointAddr),
|
||||
skb->tail + IPFIELD_ALIGN_OFFSET,
|
||||
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
|
||||
rinfo);
|
||||
|
||||
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
lbs_dev_dbg(2, &cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
|
||||
if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
|
||||
/* handle failure conditions */
|
||||
lbs_dev_dbg(1, &cardp->udev->dev, "Submit Rx URB failed\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
lbs_dev_dbg(2, &cardp->udev->dev, "Submit Rx URB success\n");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
rx_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int if_usb_submit_rx_urb_fwload(wlan_private * priv)
|
||||
{
|
||||
return __if_usb_submit_rx_urb(priv, &if_usb_receive_fwload);
|
||||
}
|
||||
|
||||
static inline int if_usb_submit_rx_urb(wlan_private * priv)
|
||||
{
|
||||
return __if_usb_submit_rx_urb(priv, &if_usb_receive);
|
||||
}
|
||||
|
||||
static void if_usb_receive_fwload(struct urb *urb)
|
||||
{
|
||||
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
|
||||
wlan_private *priv = rinfo->priv;
|
||||
struct sk_buff *skb = rinfo->skb;
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
|
||||
struct fwsyncheader *syncfwheader;
|
||||
struct bootcmdrespStr bootcmdresp;
|
||||
|
||||
if (urb->status) {
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"URB status is failed during fw load\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cardp->bootcmdresp == 0) {
|
||||
memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
|
||||
sizeof(bootcmdresp));
|
||||
if (cardp->udev->descriptor.bcdDevice < 0x3106) {
|
||||
kfree_skb(skb);
|
||||
if_usb_submit_rx_urb_fwload(priv);
|
||||
cardp->bootcmdresp = 1;
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"Received valid boot command response\n");
|
||||
return;
|
||||
}
|
||||
if (bootcmdresp.u32magicnumber != BOOT_CMD_MAGIC_NUMBER) {
|
||||
lbs_pr_info(
|
||||
"boot cmd response wrong magic number (0x%x)\n",
|
||||
bootcmdresp.u32magicnumber);
|
||||
} else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) {
|
||||
lbs_pr_info(
|
||||
"boot cmd response cmd_tag error (%d)\n",
|
||||
bootcmdresp.u8cmd_tag);
|
||||
} else if (bootcmdresp.u8result != BOOT_CMD_RESP_OK) {
|
||||
lbs_pr_info(
|
||||
"boot cmd response result error (%d)\n",
|
||||
bootcmdresp.u8result);
|
||||
} else {
|
||||
cardp->bootcmdresp = 1;
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"Received valid boot command response\n");
|
||||
}
|
||||
kfree_skb(skb);
|
||||
if_usb_submit_rx_urb_fwload(priv);
|
||||
return;
|
||||
}
|
||||
|
||||
syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
|
||||
if (!syncfwheader) {
|
||||
lbs_dev_dbg(1, &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_dev_dbg(2, &cardp->udev->dev,
|
||||
"FW received Blk with correct CRC\n");
|
||||
lbs_dev_dbg(2, &cardp->udev->dev,
|
||||
"FW received Blk seqnum = %d\n",
|
||||
syncfwheader->seqnum);
|
||||
cardp->CRC_OK = 1;
|
||||
} else {
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"FW received Blk with CRC error\n");
|
||||
cardp->CRC_OK = 0;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
if (cardp->fwfinalblk) {
|
||||
cardp->fwdnldover = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if_prog_firmware(priv);
|
||||
|
||||
if_usb_submit_rx_urb_fwload(priv);
|
||||
exit:
|
||||
kfree(syncfwheader);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#define MRVDRV_MIN_PKT_LEN 30
|
||||
|
||||
static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
|
||||
struct usb_card_rec *cardp,
|
||||
wlan_private *priv)
|
||||
{
|
||||
if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE +
|
||||
MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) {
|
||||
lbs_dev_dbg(1, &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);
|
||||
libertas_process_rxed_packet(priv, skb);
|
||||
priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
|
||||
}
|
||||
|
||||
static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
|
||||
struct sk_buff *skb,
|
||||
struct usb_card_rec *cardp,
|
||||
wlan_private *priv)
|
||||
{
|
||||
u8 *cmdbuf;
|
||||
if (recvlength > MRVDRV_SIZE_OF_CMD_BUFFER) {
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"The receive buffer is too large\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!in_interrupt())
|
||||
BUG();
|
||||
|
||||
spin_lock(&priv->adapter->driver_lock);
|
||||
/* take care of cur_cmd = NULL case by reading the
|
||||
* data to clear the interrupt */
|
||||
if (!priv->adapter->cur_cmd) {
|
||||
cmdbuf = priv->wlan_dev.upld_buf;
|
||||
priv->adapter->hisregcpy &= ~his_cmdupldrdy;
|
||||
} else
|
||||
cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr;
|
||||
|
||||
cardp->usb_int_cause |= his_cmdupldrdy;
|
||||
priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
|
||||
memcpy(cmdbuf, recvbuff + MESSAGE_HEADER_LEN,
|
||||
priv->wlan_dev.upld_len);
|
||||
|
||||
kfree_skb(skb);
|
||||
libertas_interrupt(priv->wlan_dev.netdev);
|
||||
spin_unlock(&priv->adapter->driver_lock);
|
||||
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"Wake up main thread to handle cmd response\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 read_cb_info *rinfo = (struct read_cb_info *)urb->context;
|
||||
wlan_private *priv = rinfo->priv;
|
||||
struct sk_buff *skb = rinfo->skb;
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
|
||||
|
||||
int recvlength = urb->actual_length;
|
||||
u8 *recvbuff = NULL;
|
||||
u32 recvtype;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (recvlength) {
|
||||
if (urb->status) {
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"URB status is failed\n");
|
||||
kfree_skb(skb);
|
||||
goto setup_for_next;
|
||||
}
|
||||
|
||||
recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
|
||||
memcpy(&recvtype, recvbuff, sizeof(u32));
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"Recv length = 0x%x\n", recvlength);
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"Receive type = 0x%X\n", recvtype);
|
||||
recvtype = le32_to_cpu(recvtype);
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,
|
||||
"Receive type after = 0x%X\n", recvtype);
|
||||
} else if (urb->status)
|
||||
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 cause handling */
|
||||
spin_lock(&priv->adapter->driver_lock);
|
||||
cardp->usb_event_cause = *(u32 *) (recvbuff + MESSAGE_HEADER_LEN);
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,"**EVENT** 0x%X\n",
|
||||
cardp->usb_event_cause);
|
||||
if (cardp->usb_event_cause & 0xffff0000) {
|
||||
libertas_send_tx_feedback(priv);
|
||||
break;
|
||||
}
|
||||
cardp->usb_event_cause = le32_to_cpu(cardp->usb_event_cause) << 3;
|
||||
cardp->usb_int_cause |= his_cardevent;
|
||||
kfree_skb(skb);
|
||||
libertas_interrupt(priv->wlan_dev.netdev);
|
||||
spin_unlock(&priv->adapter->driver_lock);
|
||||
goto rx_exit;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
|
||||
setup_for_next:
|
||||
if_usb_submit_rx_urb(priv);
|
||||
rx_exit:
|
||||
LEAVE();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function downloads data to FW
|
||||
* @param priv pointer to wlan_private structure
|
||||
* @param type type of data
|
||||
* @param buf pointer to data buffer
|
||||
* @param len number of bytes
|
||||
* @return 0 or -1
|
||||
*/
|
||||
int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
|
||||
{
|
||||
int ret = -1;
|
||||
u32 tmp;
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
|
||||
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,"*** type = %u\n", type);
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,"size after = %d\n", nb);
|
||||
|
||||
if (type == MVMS_CMD) {
|
||||
tmp = cpu_to_le32(CMD_TYPE_REQUEST);
|
||||
priv->wlan_dev.dnld_sent = DNLD_CMD_SENT;
|
||||
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
|
||||
MESSAGE_HEADER_LEN);
|
||||
|
||||
} else {
|
||||
tmp = cpu_to_le32(CMD_TYPE_DATA);
|
||||
priv->wlan_dev.dnld_sent = DNLD_DATA_SENT;
|
||||
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
|
||||
MESSAGE_HEADER_LEN);
|
||||
}
|
||||
|
||||
memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
|
||||
|
||||
ret =
|
||||
usb_tx_block(priv, cardp->bulk_out_buffer, nb + MESSAGE_HEADER_LEN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* called with adapter->driver_lock held */
|
||||
int libertas_sbi_get_int_status(wlan_private * priv, u8 * ireg)
|
||||
{
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
|
||||
*ireg = cardp->usb_int_cause;
|
||||
cardp->usb_int_cause = 0;
|
||||
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,"Int cause is 0x%X\n", *ireg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libertas_sbi_read_event_cause(wlan_private * priv)
|
||||
{
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
priv->adapter->eventcause = cardp->usb_event_cause;
|
||||
/* Re-submit rx urb here to avoid event lost issue */
|
||||
if_usb_submit_rx_urb(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reset_device(wlan_private *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libertas_prepare_and_send_command(priv, cmd_802_11_reset,
|
||||
cmd_act_halt, 0, 0, NULL);
|
||||
msleep_interruptible(10);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int libertas_sbi_unregister_dev(wlan_private * priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Need to send a Reset command to device before USB resources freed
|
||||
* and wlan_remove_card() called, then device can handle FW download
|
||||
* again.
|
||||
*/
|
||||
if (priv)
|
||||
reset_device(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function register usb device and initialize parameter
|
||||
* @param priv pointer to wlan_private
|
||||
* @return 0 or -1
|
||||
*/
|
||||
int libertas_sbi_register_dev(wlan_private * priv)
|
||||
{
|
||||
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
|
||||
ENTER();
|
||||
|
||||
cardp->priv = priv;
|
||||
cardp->eth_dev = priv->wlan_dev.netdev;
|
||||
priv->hotplug_device = &(cardp->udev->dev);
|
||||
|
||||
SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev));
|
||||
|
||||
lbs_dev_dbg(1, &cardp->udev->dev, "udev pointer is at %p\n",
|
||||
cardp->udev);
|
||||
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int libertas_sbi_prog_firmware(wlan_private * priv)
|
||||
{
|
||||
struct usb_card_rec *cardp = priv->wlan_dev.card;
|
||||
int i = 0;
|
||||
static int reset_count = 10;
|
||||
|
||||
ENTER();
|
||||
|
||||
cardp->rinfo.priv = priv;
|
||||
|
||||
restart:
|
||||
if (if_usb_submit_rx_urb_fwload(priv) < 0) {
|
||||
lbs_dev_dbg(1, &cardp->udev->dev, "URB submission is failed\n");
|
||||
LEAVE();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_BOOT_COMMAND
|
||||
cardp->bootcmdresp = 0;
|
||||
do {
|
||||
int j = 0;
|
||||
i++;
|
||||
/* Issue Boot command = 1, Boot from Download-FW */
|
||||
if_usb_issue_boot_command(priv, 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) {
|
||||
libertas_do_reset(priv);
|
||||
goto restart;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = 0;
|
||||
priv->adapter->fw_ready = 0;
|
||||
|
||||
cardp->totalbytes = 0;
|
||||
cardp->fwlastblksent = 0;
|
||||
cardp->CRC_OK = 1;
|
||||
cardp->fwdnldover = 0;
|
||||
cardp->fwseqnum = -1;
|
||||
cardp->totalbytes = 0;
|
||||
cardp->fwfinalblk = 0;
|
||||
|
||||
if_prog_firmware(priv);
|
||||
|
||||
do {
|
||||
lbs_dev_dbg(1, &cardp->udev->dev,"Wlan sched timeout\n");
|
||||
i++;
|
||||
msleep_interruptible(100);
|
||||
if (priv->adapter->surpriseremoved || i >= 20)
|
||||
break;
|
||||
} while (!cardp->fwdnldover);
|
||||
|
||||
if (!cardp->fwdnldover) {
|
||||
lbs_pr_info("failed to load fw, resetting device!\n");
|
||||
if (--reset_count >= 0) {
|
||||
libertas_do_reset(priv);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
|
||||
LEAVE();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if_usb_submit_rx_urb(priv);
|
||||
|
||||
/* Delay 200 ms to waiting for the FW ready */
|
||||
msleep_interruptible(200);
|
||||
|
||||
priv->adapter->fw_ready = 1;
|
||||
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Given a usb_card_rec return its wlan_private
|
||||
* @param card pointer to a usb_card_rec
|
||||
* @return pointer to wlan_private
|
||||
*/
|
||||
wlan_private *libertas_sbi_get_priv(void *card)
|
||||
{
|
||||
struct usb_card_rec *cardp = card;
|
||||
return cardp->priv;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PM
|
||||
int libertas_sbi_suspend(wlan_private * priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libertas_sbi_resume(wlan_private * priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
{
|
||||
struct usb_card_rec *cardp = usb_get_intfdata(intf);
|
||||
wlan_private *priv = cardp->priv;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (priv->adapter->psstate != PS_STATE_FULL_POWER)
|
||||
return -1;
|
||||
|
||||
netif_device_detach(cardp->eth_dev);
|
||||
|
||||
/* Unlink tx & rx urb */
|
||||
usb_kill_urb(cardp->tx_urb);
|
||||
usb_kill_urb(cardp->rx_urb);
|
||||
|
||||
cardp->rx_urb_recall = 1;
|
||||
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int if_usb_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_card_rec *cardp = usb_get_intfdata(intf);
|
||||
|
||||
ENTER();
|
||||
|
||||
cardp->rx_urb_recall = 0;
|
||||
|
||||
if_usb_submit_rx_urb(cardp->priv);
|
||||
|
||||
netif_device_attach(cardp->eth_dev);
|
||||
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define if_usb_suspend NULL
|
||||
#define if_usb_resume NULL
|
||||
#endif
|
||||
|
||||
static struct usb_driver if_usb_driver = {
|
||||
/* driver name */
|
||||
.name = usbdriver_name,
|
||||
/* probe function name */
|
||||
.probe = if_usb_probe,
|
||||
/* disconnect function name */
|
||||
.disconnect = if_usb_disconnect,
|
||||
/* device signature table */
|
||||
.id_table = if_usb_table,
|
||||
.suspend = if_usb_suspend,
|
||||
.resume = if_usb_resume,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This function registers driver.
|
||||
* @param add pointer to add_card callback function
|
||||
* @param remove pointer to remove card callback function
|
||||
* @param arg pointer to call back function parameter
|
||||
* @return dummy success variable
|
||||
*/
|
||||
int libertas_sbi_register(void)
|
||||
{
|
||||
/*
|
||||
* API registers the Marvell USB driver
|
||||
* to the USB system
|
||||
*/
|
||||
usb_register(&if_usb_driver);
|
||||
|
||||
/* Return success to wlan layer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function removes usb driver.
|
||||
* @return N/A
|
||||
*/
|
||||
void libertas_sbi_unregister(void)
|
||||
{
|
||||
/* API unregisters the driver from USB subsystem */
|
||||
usb_deregister(&if_usb_driver);
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* 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 USB8388_VID_1 0x1286
|
||||
#define USB8388_PID_1 0x2001
|
||||
#define USB8388_VID_2 0x05a3
|
||||
#define USB8388_PID_2 0x8388
|
||||
|
||||
#ifdef SUPPORT_BOOT_COMMAND
|
||||
#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 /* M=>0x4D,R=>0x52,V=>0x56,L=>0x4C */
|
||||
|
||||
struct bootcmdstr
|
||||
{
|
||||
u32 u32magicnumber;
|
||||
u8 u8cmd_tag;
|
||||
u8 au8dumy[11];
|
||||
};
|
||||
|
||||
#define BOOT_CMD_RESP_OK 0x0001
|
||||
#define BOOT_CMD_RESP_FAIL 0x0000
|
||||
|
||||
struct bootcmdrespStr
|
||||
{
|
||||
u32 u32magicnumber;
|
||||
u8 u8cmd_tag;
|
||||
u8 u8result;
|
||||
u8 au8dumy[2];
|
||||
};
|
||||
#endif /* SUPPORT_BOOT_COMMAND */
|
||||
|
||||
/* read callback private data */
|
||||
struct read_cb_info {
|
||||
wlan_private *priv;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
|
||||
/** USB card description structure*/
|
||||
struct usb_card_rec {
|
||||
struct net_device *eth_dev;
|
||||
struct usb_device *udev;
|
||||
struct urb *rx_urb, *tx_urb;
|
||||
void *priv;
|
||||
struct read_cb_info rinfo;
|
||||
|
||||
int bulk_in_size;
|
||||
u8 bulk_in_endpointAddr;
|
||||
|
||||
u8 *bulk_out_buffer;
|
||||
int bulk_out_size;
|
||||
u8 bulk_out_endpointAddr;
|
||||
|
||||
u8 CRC_OK;
|
||||
u32 fwseqnum;
|
||||
u32 lastseqnum;
|
||||
u32 totalbytes;
|
||||
u32 fwlastblksent;
|
||||
u8 fwdnldover;
|
||||
u8 fwfinalblk;
|
||||
|
||||
u32 usb_event_cause;
|
||||
u8 usb_int_cause;
|
||||
|
||||
u8 rx_urb_recall;
|
||||
|
||||
u8 bootcmdresp;
|
||||
};
|
||||
|
||||
/** fwheader */
|
||||
struct fwheader {
|
||||
u32 dnldcmd;
|
||||
u32 baseaddr;
|
||||
u32 datalength;
|
||||
u32 CRC;
|
||||
};
|
||||
|
||||
#define FW_MAX_DATA_BLK_SIZE 600
|
||||
/** FWData */
|
||||
struct FWData {
|
||||
struct fwheader fwheader;
|
||||
u32 seqnum;
|
||||
u8 data[FW_MAX_DATA_BLK_SIZE];
|
||||
};
|
||||
|
||||
/** fwsyncheader */
|
||||
struct fwsyncheader {
|
||||
u32 cmd;
|
||||
u32 seqnum;
|
||||
};
|
||||
|
||||
#define FW_HAS_DATA_TO_RECV 0x00000001
|
||||
#define FW_HAS_LAST_BLOCK 0x00000004
|
||||
|
||||
#define FW_DATA_XMIT_SIZE \
|
||||
sizeof(struct fwheader) + fwdata->fwheader.datalength + sizeof(u32)
|
||||
|
||||
int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb);
|
||||
void if_usb_free(struct usb_card_rec *cardp);
|
||||
int if_usb_issue_boot_command(wlan_private *priv, int ivalue);
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,64 @@
|
|||
/* -*- mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
|
||||
/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
|
||||
|
||||
/**
|
||||
* Interface for the wlan infrastructure and adhoc join routines
|
||||
*
|
||||
* Driver interface functions and type declarations for the join module
|
||||
* implemented in wlan_join.c. Process all start/join requests for
|
||||
* both adhoc and infrastructure networks
|
||||
*/
|
||||
#ifndef _WLAN_JOIN_H
|
||||
#define _WLAN_JOIN_H
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
struct cmd_ds_command;
|
||||
extern int libertas_cmd_80211_authenticate(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
extern int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
extern int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd);
|
||||
extern int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pssid);
|
||||
extern int libertas_cmd_80211_deauthenticate(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd);
|
||||
extern int libertas_cmd_80211_associate(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
|
||||
extern int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
|
||||
struct cmd_ds_command *resp);
|
||||
extern int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
|
||||
struct cmd_ds_command *resp);
|
||||
extern int libertas_ret_80211_disassociate(wlan_private * priv,
|
||||
struct cmd_ds_command *resp);
|
||||
extern int libertas_ret_80211_associate(wlan_private * priv,
|
||||
struct cmd_ds_command *resp);
|
||||
|
||||
extern int libertas_idle_on(wlan_private * priv);
|
||||
extern int libertas_idle_off(wlan_private * priv);
|
||||
|
||||
extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
|
||||
extern int libertas_reassociation_thread(void *data);
|
||||
|
||||
struct WLAN_802_11_SSID;
|
||||
struct bss_descriptor;
|
||||
|
||||
extern int libertas_start_adhoc_network(wlan_private * priv,
|
||||
struct WLAN_802_11_SSID *adhocssid);
|
||||
extern int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor *pbssdesc);
|
||||
extern int libertas_stop_adhoc_network(wlan_private * priv);
|
||||
|
||||
extern int libertas_send_deauthentication(wlan_private * priv);
|
||||
extern int libertas_send_deauth(wlan_private * priv);
|
||||
|
||||
extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
|
||||
|
||||
int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc);
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,57 @@
|
|||
#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)
|
||||
|
|
@ -0,0 +1,459 @@
|
|||
/**
|
||||
* 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(wlan_private * priv, struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* @brief This function computes the avgSNR .
|
||||
*
|
||||
* @param priv A pointer to wlan_private structure
|
||||
* @return avgSNR
|
||||
*/
|
||||
static u8 wlan_getavgsnr(wlan_private * priv)
|
||||
{
|
||||
u8 i;
|
||||
u16 temp = 0;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
if (adapter->numSNRNF == 0)
|
||||
return 0;
|
||||
for (i = 0; i < adapter->numSNRNF; i++)
|
||||
temp += adapter->rawSNR[i];
|
||||
return (u8) (temp / adapter->numSNRNF);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function computes the AvgNF
|
||||
*
|
||||
* @param priv A pointer to wlan_private structure
|
||||
* @return AvgNF
|
||||
*/
|
||||
static u8 wlan_getavgnf(wlan_private * priv)
|
||||
{
|
||||
u8 i;
|
||||
u16 temp = 0;
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
if (adapter->numSNRNF == 0)
|
||||
return 0;
|
||||
for (i = 0; i < adapter->numSNRNF; i++)
|
||||
temp += adapter->rawNF[i];
|
||||
return (u8) (temp / adapter->numSNRNF);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function save the raw SNR/NF to our internel buffer
|
||||
*
|
||||
* @param priv A pointer to wlan_private structure
|
||||
* @param prxpd A pointer to rxpd structure of received packet
|
||||
* @return n/a
|
||||
*/
|
||||
static void wlan_save_rawSNRNF(wlan_private * priv, struct rxpd *p_rx_pd)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
if (adapter->numSNRNF < adapter->data_avg_factor)
|
||||
adapter->numSNRNF++;
|
||||
adapter->rawSNR[adapter->nextSNRNF] = p_rx_pd->snr;
|
||||
adapter->rawNF[adapter->nextSNRNF] = p_rx_pd->nf;
|
||||
adapter->nextSNRNF++;
|
||||
if (adapter->nextSNRNF >= adapter->data_avg_factor)
|
||||
adapter->nextSNRNF = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function computes the RSSI in received packet.
|
||||
*
|
||||
* @param priv A pointer to wlan_private structure
|
||||
* @param prxpd A pointer to rxpd structure of received packet
|
||||
* @return n/a
|
||||
*/
|
||||
static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
|
||||
ENTER();
|
||||
|
||||
lbs_pr_debug(1, "rxpd: SNR = %d, NF = %d\n", p_rx_pd->snr, p_rx_pd->nf);
|
||||
lbs_pr_debug(1, "Before computing SNR: SNR- avg = %d, NF-avg = %d\n",
|
||||
adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
|
||||
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
|
||||
|
||||
adapter->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
|
||||
adapter->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
|
||||
wlan_save_rawSNRNF(priv, p_rx_pd);
|
||||
|
||||
adapter->rxpd_rate = p_rx_pd->rx_rate;
|
||||
|
||||
adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getavgsnr(priv) * AVG_SCALE;
|
||||
adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getavgnf(priv) * AVG_SCALE;
|
||||
lbs_pr_debug(1, "After computing SNR: SNR-avg = %d, NF-avg = %d\n",
|
||||
adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
|
||||
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
|
||||
|
||||
adapter->RSSI[TYPE_RXPD][TYPE_NOAVG] =
|
||||
CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_NOAVG],
|
||||
adapter->NF[TYPE_RXPD][TYPE_NOAVG]);
|
||||
|
||||
adapter->RSSI[TYPE_RXPD][TYPE_AVG] =
|
||||
CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
|
||||
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
|
||||
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
|
||||
{
|
||||
lbs_pr_debug(1, "skb->data=%p\n", skb->data);
|
||||
|
||||
if(IS_MESH_FRAME(skb))
|
||||
skb->dev = priv->mesh_dev;
|
||||
else
|
||||
skb->dev = priv->wlan_dev.netdev;
|
||||
skb->protocol = eth_type_trans(skb, priv->wlan_dev.netdev);
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function processes received packet and forwards it
|
||||
* to kernel/upper layer
|
||||
*
|
||||
* @param priv A pointer to wlan_private
|
||||
* @param skb A pointer to skb which includes the received packet
|
||||
* @return 0 or -1
|
||||
*/
|
||||
int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
|
||||
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 };
|
||||
|
||||
ENTER();
|
||||
|
||||
if (priv->adapter->debugmode & MRVDRV_DEBUG_RX_PATH)
|
||||
lbs_dbg_hex("RX packet: ", skb->data,
|
||||
min_t(unsigned int, skb->len, 100));
|
||||
|
||||
if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
|
||||
return process_rxed_802_11_packet(priv, skb);
|
||||
|
||||
p_rx_pkt = (struct rxpackethdr *) skb->data;
|
||||
p_rx_pd = &p_rx_pkt->rx_pd;
|
||||
if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
|
||||
SET_MESH_FRAME(skb);
|
||||
else
|
||||
UNSET_MESH_FRAME(skb);
|
||||
|
||||
lbs_dbg_hex("RX Data: Before chop rxpd", skb->data,
|
||||
min_t(unsigned int, skb->len, 100));
|
||||
|
||||
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
|
||||
lbs_pr_debug(1, "RX error: 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 & MRVDRV_RXPD_STATUS_OK)) {
|
||||
lbs_pr_debug(1, "RX error: frame received with bad status\n");
|
||||
lbs_pr_alert("rxpd Not OK\n");
|
||||
priv->stats.rx_errors++;
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n",
|
||||
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
|
||||
|
||||
lbs_dbg_hex("RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
|
||||
sizeof(p_rx_pkt->eth803_hdr.dest_addr));
|
||||
lbs_dbg_hex("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_dbg_hex("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 (adapter->is_datarate_auto)
|
||||
adapter->datarate = libertas_index_to_data_rate(p_rx_pd->rx_rate);
|
||||
|
||||
wlan_compute_rssi(priv, p_rx_pd);
|
||||
|
||||
lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
|
||||
if (libertas_upload_rx_packet(priv, skb)) {
|
||||
lbs_pr_debug(1, "RX error: libertas_upload_rx_packet"
|
||||
" returns failure\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
priv->stats.rx_bytes += skb->len;
|
||||
priv->stats.rx_packets++;
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
LEAVE();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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: /* 6 Mbps */
|
||||
return 12;
|
||||
case 5: /* 9 Mbps */
|
||||
return 18;
|
||||
case 6: /* 12 Mbps */
|
||||
return 24;
|
||||
case 7: /* 18 Mbps */
|
||||
return 36;
|
||||
case 8: /* 24 Mbps */
|
||||
return 48;
|
||||
case 9: /* 36 Mbps */
|
||||
return 72;
|
||||
case 10: /* 48 Mbps */
|
||||
return 96;
|
||||
case 11: /* 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 wlan_private
|
||||
* @param skb A pointer to skb which includes the received packet
|
||||
* @return 0 or -1
|
||||
*/
|
||||
static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
|
||||
struct rx80211packethdr *p_rx_pkt;
|
||||
struct rxpd *prxpd;
|
||||
struct rx_radiotap_hdr radiotap_hdr;
|
||||
struct rx_radiotap_hdr *pradiotap_hdr;
|
||||
|
||||
ENTER();
|
||||
|
||||
p_rx_pkt = (struct rx80211packethdr *) skb->data;
|
||||
prxpd = &p_rx_pkt->rx_pd;
|
||||
|
||||
// lbs_dbg_hex("RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
|
||||
|
||||
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
|
||||
lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n");
|
||||
priv->stats.rx_length_errors++;
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check rxpd status and update 802.3 stat,
|
||||
*/
|
||||
if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK)) {
|
||||
//lbs_pr_debug(1, "RX error: frame received with bad status\n");
|
||||
priv->stats.rx_errors++;
|
||||
}
|
||||
|
||||
lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n",
|
||||
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
|
||||
|
||||
/* create the exported radio header */
|
||||
switch (priv->adapter->radiomode) {
|
||||
case WLAN_RADIOMODE_NONE:
|
||||
/* no radio header */
|
||||
/* chop the rxpd */
|
||||
skb_pull(skb, sizeof(struct rxpd));
|
||||
break;
|
||||
|
||||
case WLAN_RADIOMODE_RADIOTAP:
|
||||
/* 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 = sizeof(struct rx_radiotap_hdr);
|
||||
radiotap_hdr.hdr.it_present = 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 & MRVDRV_RXPD_STATUS_OK))
|
||||
radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
|
||||
//memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
|
||||
|
||||
// lbs_dbg_hex1("RX radiomode packet BEF: ", skb->data, min(skb->len, 100));
|
||||
|
||||
/* 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__);
|
||||
}
|
||||
|
||||
pradiotap_hdr =
|
||||
(struct rx_radiotap_hdr *)skb_push(skb,
|
||||
sizeof(struct
|
||||
rx_radiotap_hdr));
|
||||
memcpy(pradiotap_hdr, &radiotap_hdr,
|
||||
sizeof(struct rx_radiotap_hdr));
|
||||
//lbs_dbg_hex1("RX radiomode packet AFT: ", skb->data, min(skb->len, 100));
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown header */
|
||||
lbs_pr_alert( "Unknown radiomode (%i)\n",
|
||||
priv->adapter->radiomode);
|
||||
/* don't export any header */
|
||||
/* chop the rxpd */
|
||||
skb_pull(skb, sizeof(struct rxpd));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Take the data rate from the rxpd structure
|
||||
* only if the rate is auto
|
||||
*/
|
||||
if (adapter->is_datarate_auto) {
|
||||
adapter->datarate = libertas_index_to_data_rate(prxpd->rx_rate);
|
||||
}
|
||||
|
||||
wlan_compute_rssi(priv, prxpd);
|
||||
|
||||
lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
|
||||
|
||||
if (libertas_upload_rx_packet(priv, skb)) {
|
||||
lbs_pr_debug(1, "RX error: libertas_upload_rx_packet "
|
||||
"returns failure\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
priv->stats.rx_bytes += skb->len;
|
||||
priv->stats.rx_packets++;
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
LEAVE();
|
||||
|
||||
skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */
|
||||
|
||||
return (ret);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* This file contains IF layer definitions.
|
||||
*/
|
||||
|
||||
#ifndef _SBI_H_
|
||||
#define _SBI_H_
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/** INT status Bit Definition*/
|
||||
#define his_cmddnldrdy 0x01
|
||||
#define his_cardevent 0x02
|
||||
#define his_cmdupldrdy 0x04
|
||||
|
||||
#ifndef DEV_NAME_LEN
|
||||
#define DEV_NAME_LEN 32
|
||||
#endif
|
||||
|
||||
#define SBI_EVENT_CAUSE_SHIFT 3
|
||||
|
||||
/* Probe and Check if the card is present*/
|
||||
int libertas_sbi_register_dev(wlan_private * priv);
|
||||
int libertas_sbi_unregister_dev(wlan_private *);
|
||||
int libertas_sbi_get_int_status(wlan_private * priv, u8 *);
|
||||
int libertas_sbi_register(void);
|
||||
void libertas_sbi_unregister(void);
|
||||
int libertas_sbi_prog_firmware(wlan_private *);
|
||||
|
||||
int libertas_sbi_read_event_cause(wlan_private *);
|
||||
int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
|
||||
wlan_private *libertas_sbi_get_priv(void *card);
|
||||
|
||||
#ifdef ENABLE_PM
|
||||
int libertas_sbi_suspend(wlan_private *);
|
||||
int libertas_sbi_resume(wlan_private *);
|
||||
#endif
|
||||
|
||||
#endif /* _SBI_H */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,216 @@
|
|||
/* -*- mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
|
||||
/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
|
||||
|
||||
/**
|
||||
* Interface for the wlan network scan routines
|
||||
*
|
||||
* Driver interface functions and type declarations for the scan module
|
||||
* implemented in wlan_scan.c.
|
||||
*/
|
||||
#ifndef _WLAN_SCAN_H
|
||||
#define _WLAN_SCAN_H
|
||||
|
||||
#include "hostcmd.h"
|
||||
|
||||
/**
|
||||
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
|
||||
*
|
||||
* @sa wlan_ioctl_user_scan_cfg
|
||||
*/
|
||||
#define WLAN_IOCTL_USER_SCAN_CHAN_MAX 50
|
||||
|
||||
//! Infrastructure BSS scan type in wlan_scan_cmd_config
|
||||
#define WLAN_SCAN_BSS_TYPE_BSS 1
|
||||
|
||||
//! Adhoc BSS scan type in wlan_scan_cmd_config
|
||||
#define WLAN_SCAN_BSS_TYPE_IBSS 2
|
||||
|
||||
//! Adhoc or Infrastructure BSS scan type in wlan_scan_cmd_config, no filter
|
||||
#define WLAN_SCAN_BSS_TYPE_ANY 3
|
||||
|
||||
/**
|
||||
* @brief Structure used internally in the wlan driver to configure a scan.
|
||||
*
|
||||
* Sent to the command processing module to configure the firmware
|
||||
* scan command prepared by libertas_cmd_80211_scan.
|
||||
*
|
||||
* @sa wlan_scan_networks
|
||||
*
|
||||
*/
|
||||
struct wlan_scan_cmd_config {
|
||||
/**
|
||||
* @brief BSS type to be sent in the firmware command
|
||||
*
|
||||
* Field can be used to restrict the types of networks returned in the
|
||||
* scan. valid settings are:
|
||||
*
|
||||
* - WLAN_SCAN_BSS_TYPE_BSS (infrastructure)
|
||||
* - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
|
||||
* - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
|
||||
*/
|
||||
u8 bsstype;
|
||||
|
||||
/**
|
||||
* @brief Specific BSSID used to filter scan results in the firmware
|
||||
*/
|
||||
u8 specificBSSID[ETH_ALEN];
|
||||
|
||||
/**
|
||||
* @brief length of TLVs sent in command starting at tlvBuffer
|
||||
*/
|
||||
int tlvbufferlen;
|
||||
|
||||
/**
|
||||
* @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command
|
||||
*
|
||||
* @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t
|
||||
* @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t
|
||||
*/
|
||||
u8 tlvbuffer[1]; //!< SSID TLV(s) and ChanList TLVs are stored here
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg
|
||||
*
|
||||
* Multiple instances of this structure are included in the IOCTL command
|
||||
* to configure a instance of a scan on the specific channel.
|
||||
*/
|
||||
struct wlan_ioctl_user_scan_chan {
|
||||
u8 channumber; //!< channel Number to scan
|
||||
u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
|
||||
u8 scantype; //!< Scan type: Active = 0, Passive = 1
|
||||
u16 scantime; //!< Scan duration in milliseconds; if 0 default used
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief IOCTL input structure to configure an immediate scan cmd to firmware
|
||||
*
|
||||
* Used in the setuserscan (WLAN_SET_USER_SCAN) private ioctl. Specifies
|
||||
* a number of parameters to be used in general for the scan as well
|
||||
* as a channel list (wlan_ioctl_user_scan_chan) for each scan period
|
||||
* desired.
|
||||
*
|
||||
* @sa libertas_set_user_scan_ioctl
|
||||
*/
|
||||
struct wlan_ioctl_user_scan_cfg {
|
||||
|
||||
/**
|
||||
* @brief Flag set to keep the previous scan table intact
|
||||
*
|
||||
* If set, the scan results will accumulate, replacing any previous
|
||||
* matched entries for a BSS with the new scan data
|
||||
*/
|
||||
u8 keeppreviousscan; //!< Do not erase the existing scan results
|
||||
|
||||
/**
|
||||
* @brief BSS type to be sent in the firmware command
|
||||
*
|
||||
* Field can be used to restrict the types of networks returned in the
|
||||
* scan. valid settings are:
|
||||
*
|
||||
* - WLAN_SCAN_BSS_TYPE_BSS (infrastructure)
|
||||
* - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
|
||||
* - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
|
||||
*/
|
||||
u8 bsstype;
|
||||
|
||||
/**
|
||||
* @brief Configure the number of probe requests for active chan scans
|
||||
*/
|
||||
u8 numprobes;
|
||||
|
||||
/**
|
||||
* @brief BSSID filter sent in the firmware command to limit the results
|
||||
*/
|
||||
u8 specificBSSID[ETH_ALEN];
|
||||
|
||||
/**
|
||||
* @brief SSID filter sent in the firmware command to limit the results
|
||||
*/
|
||||
char specificSSID[IW_ESSID_MAX_SIZE + 1];
|
||||
|
||||
/**
|
||||
* @brief Variable number (fixed maximum) of channels to scan up
|
||||
*/
|
||||
struct wlan_ioctl_user_scan_chan chanlist[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure used to store information for each beacon/probe response
|
||||
*/
|
||||
struct bss_descriptor {
|
||||
u8 macaddress[ETH_ALEN];
|
||||
|
||||
struct WLAN_802_11_SSID ssid;
|
||||
|
||||
/* WEP encryption requirement */
|
||||
u32 privacy;
|
||||
|
||||
/* receive signal strength in dBm */
|
||||
long rssi;
|
||||
|
||||
u32 channel;
|
||||
|
||||
u16 beaconperiod;
|
||||
|
||||
u32 atimwindow;
|
||||
|
||||
enum WLAN_802_11_NETWORK_INFRASTRUCTURE inframode;
|
||||
u8 libertas_supported_rates[WLAN_SUPPORTED_RATES];
|
||||
|
||||
int extra_ie;
|
||||
|
||||
u8 timestamp[8]; //!< TSF value included in the beacon/probe response
|
||||
union ieeetypes_phyparamset phyparamset;
|
||||
union IEEEtypes_ssparamset ssparamset;
|
||||
struct ieeetypes_capinfo cap;
|
||||
u8 datarates[WLAN_SUPPORTED_RATES];
|
||||
|
||||
__le64 networktsf; //!< TSF timestamp from the current firmware TSF
|
||||
|
||||
struct ieeetypes_countryinfofullset countryinfo;
|
||||
|
||||
struct WPA_SUPPLICANT wpa_supplicant;
|
||||
struct WPA_SUPPLICANT wpa2_supplicant;
|
||||
|
||||
};
|
||||
|
||||
extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1,
|
||||
struct WLAN_802_11_SSID *ssid2);
|
||||
extern int libertas_find_SSID_in_list(wlan_adapter * adapter, struct WLAN_802_11_SSID *ssid,
|
||||
u8 * bssid, int mode);
|
||||
int libertas_find_best_SSID_in_list(wlan_adapter * adapter, enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode);
|
||||
extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, int mode);
|
||||
|
||||
int libertas_find_best_network_SSID(wlan_private * priv,
|
||||
struct WLAN_802_11_SSID *pSSID,
|
||||
enum WLAN_802_11_NETWORK_INFRASTRUCTURE preferred_mode,
|
||||
enum WLAN_802_11_NETWORK_INFRASTRUCTURE *out_mode);
|
||||
|
||||
extern int libertas_send_specific_SSID_scan(wlan_private * priv,
|
||||
struct WLAN_802_11_SSID *prequestedssid,
|
||||
u8 keeppreviousscan);
|
||||
extern int libertas_send_specific_BSSID_scan(wlan_private * priv,
|
||||
u8 * bssid, u8 keeppreviousscan);
|
||||
|
||||
extern int libertas_cmd_80211_scan(wlan_private * priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
|
||||
extern int libertas_ret_80211_scan(wlan_private * priv,
|
||||
struct cmd_ds_command *resp);
|
||||
|
||||
int wlan_scan_networks(wlan_private * priv,
|
||||
const struct wlan_ioctl_user_scan_cfg * puserscanin);
|
||||
|
||||
struct ifreq;
|
||||
|
||||
struct iw_point;
|
||||
struct iw_param;
|
||||
struct iw_request_info;
|
||||
extern int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
|
||||
struct iw_point *dwrq, char *extra);
|
||||
extern int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
|
||||
struct iw_param *vwrq, char *extra);
|
||||
|
||||
#endif /* _WLAN_SCAN_H */
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef __WLAN_THREAD_H_
|
||||
#define __WLAN_THREAD_H_
|
||||
|
||||
#include <linux/kthread.h>
|
||||
|
||||
struct wlan_thread {
|
||||
struct task_struct *task;
|
||||
wait_queue_head_t waitq;
|
||||
pid_t pid;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
static inline void wlan_activate_thread(struct wlan_thread * thr)
|
||||
{
|
||||
/** Record the thread pid */
|
||||
thr->pid = current->pid;
|
||||
|
||||
/** Initialize the wait queue */
|
||||
init_waitqueue_head(&thr->waitq);
|
||||
}
|
||||
|
||||
static inline void wlan_deactivate_thread(struct wlan_thread * thr)
|
||||
{
|
||||
ENTER();
|
||||
|
||||
thr->pid = 0;
|
||||
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
static inline void wlan_create_thread(int (*wlanfunc) (void *),
|
||||
struct wlan_thread * thr, char *name)
|
||||
{
|
||||
thr->task = kthread_run(wlanfunc, thr, "%s", name);
|
||||
}
|
||||
|
||||
static inline int wlan_terminate_thread(struct wlan_thread * thr)
|
||||
{
|
||||
ENTER();
|
||||
|
||||
/* Check if the thread is active or not */
|
||||
if (!thr->pid) {
|
||||
printk(KERN_ERR "Thread does not exist\n");
|
||||
return -1;
|
||||
}
|
||||
kthread_stop(thr->task);
|
||||
|
||||
LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,285 @@
|
|||
/**
|
||||
* This file contains the handling of TX in wlan driver.
|
||||
*/
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "hostcmd.h"
|
||||
#include "radiotap.h"
|
||||
#include "sbi.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 processes a single packet and sends
|
||||
* to IF layer
|
||||
*
|
||||
* @param priv A pointer to wlan_private structure
|
||||
* @param skb A pointer to skb which includes TX packet
|
||||
* @return 0 or -1
|
||||
*/
|
||||
static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
struct txpd localtxpd;
|
||||
struct txpd *plocaltxpd = &localtxpd;
|
||||
u8 *p802x_hdr;
|
||||
struct tx_radiotap_hdr *pradiotap_hdr;
|
||||
u32 new_rate;
|
||||
u8 *ptr = priv->adapter->tmptxbuf;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (priv->adapter->surpriseremoved)
|
||||
return -1;
|
||||
|
||||
if ((priv->adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
|
||||
lbs_dbg_hex("TX packet: ", skb->data,
|
||||
min_t(unsigned int, skb->len, 100));
|
||||
|
||||
if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
|
||||
lbs_pr_debug(1, "Tx error: Bad skb length %d : %d\n",
|
||||
skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(plocaltxpd, 0, sizeof(struct txpd));
|
||||
|
||||
plocaltxpd->tx_packet_length = skb->len;
|
||||
|
||||
/* offset of actual data */
|
||||
plocaltxpd->tx_packet_location = sizeof(struct txpd);
|
||||
|
||||
/* TxCtrl set by user or default */
|
||||
plocaltxpd->tx_control = adapter->pkttxctrl;
|
||||
|
||||
p802x_hdr = skb->data;
|
||||
if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
|
||||
|
||||
/* locate radiotap header */
|
||||
pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data;
|
||||
|
||||
/* set txpd fields from the radiotap header */
|
||||
new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
|
||||
if (new_rate != 0) {
|
||||
/* erase tx_control[4:0] */
|
||||
plocaltxpd->tx_control &= ~0x1f;
|
||||
/* write new tx_control[4:0] */
|
||||
plocaltxpd->tx_control |= new_rate;
|
||||
}
|
||||
|
||||
/* skip the radiotap header */
|
||||
p802x_hdr += sizeof(struct tx_radiotap_hdr);
|
||||
plocaltxpd->tx_packet_length -= sizeof(struct tx_radiotap_hdr);
|
||||
|
||||
}
|
||||
/* copy destination address from 802.3 or 802.11 header */
|
||||
if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
|
||||
memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
|
||||
else
|
||||
memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
|
||||
|
||||
lbs_dbg_hex("txpd", (u8 *) plocaltxpd, sizeof(struct txpd));
|
||||
|
||||
if (IS_MESH_FRAME(skb)) {
|
||||
plocaltxpd->tx_control |= TxPD_MESH_FRAME;
|
||||
}
|
||||
|
||||
memcpy(ptr, plocaltxpd, sizeof(struct txpd));
|
||||
|
||||
ptr += sizeof(struct txpd);
|
||||
|
||||
lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, plocaltxpd->tx_packet_length);
|
||||
memcpy(ptr, p802x_hdr, plocaltxpd->tx_packet_length);
|
||||
ret = libertas_sbi_host_to_card(priv, MVMS_DAT,
|
||||
priv->adapter->tmptxbuf,
|
||||
plocaltxpd->tx_packet_length +
|
||||
sizeof(struct txpd));
|
||||
|
||||
if (ret) {
|
||||
lbs_pr_debug(1, "Tx error: libertas_sbi_host_to_card failed: 0x%X\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lbs_pr_debug(1, "SendSinglePacket succeeds\n");
|
||||
|
||||
done:
|
||||
if (!ret) {
|
||||
priv->stats.tx_packets++;
|
||||
priv->stats.tx_bytes += skb->len;
|
||||
} else {
|
||||
priv->stats.tx_dropped++;
|
||||
priv->stats.tx_errors++;
|
||||
}
|
||||
|
||||
if (!ret && priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
|
||||
/* Keep the skb to echo it back once Tx feedback is
|
||||
received from FW */
|
||||
skb_orphan(skb);
|
||||
/* stop processing outgoing pkts */
|
||||
netif_stop_queue(priv->wlan_dev.netdev);
|
||||
/* freeze any packets already in our queues */
|
||||
priv->adapter->TxLockFlag = 1;
|
||||
} else {
|
||||
dev_kfree_skb_any(skb);
|
||||
priv->adapter->currenttxskb = NULL;
|
||||
}
|
||||
|
||||
LEAVE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void libertas_tx_runqueue(wlan_private *priv)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
int i;
|
||||
|
||||
spin_lock(&adapter->txqueue_lock);
|
||||
for (i = 0; i < adapter->tx_queue_idx; i++) {
|
||||
struct sk_buff *skb = adapter->tx_queue_ps[i];
|
||||
spin_unlock(&adapter->txqueue_lock);
|
||||
SendSinglePacket(priv, skb);
|
||||
spin_lock(&adapter->txqueue_lock);
|
||||
}
|
||||
adapter->tx_queue_idx = 0;
|
||||
spin_unlock(&adapter->txqueue_lock);
|
||||
}
|
||||
|
||||
static void wlan_tx_queue(wlan_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
|
||||
spin_lock(&adapter->txqueue_lock);
|
||||
|
||||
WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
|
||||
adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
|
||||
if (adapter->tx_queue_idx == NR_TX_QUEUE)
|
||||
netif_stop_queue(priv->wlan_dev.netdev);
|
||||
else
|
||||
netif_start_queue(priv->wlan_dev.netdev);
|
||||
|
||||
spin_unlock(&adapter->txqueue_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function checks the conditions and sends packet to IF
|
||||
* layer if everything is ok.
|
||||
*
|
||||
* @param priv A pointer to wlan_private structure
|
||||
* @return n/a
|
||||
*/
|
||||
int libertas_process_tx(wlan_private * priv, struct sk_buff *skb)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
ENTER();
|
||||
|
||||
lbs_dbg_hex("TX Data", skb->data, min_t(unsigned int, skb->len, 100));
|
||||
|
||||
if (priv->wlan_dev.dnld_sent) {
|
||||
lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n",
|
||||
priv->wlan_dev.dnld_sent);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((priv->adapter->psstate == PS_STATE_SLEEP) ||
|
||||
(priv->adapter->psstate == PS_STATE_PRE_SLEEP)) {
|
||||
wlan_tx_queue(priv, skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->adapter->currenttxskb = skb;
|
||||
|
||||
ret = SendSinglePacket(priv, skb);
|
||||
done:
|
||||
LEAVE();
|
||||
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 wlan_private structure
|
||||
* @param status A 32 bit value containing transmission status.
|
||||
*
|
||||
* @returns void
|
||||
*/
|
||||
void libertas_send_tx_feedback(wlan_private * priv)
|
||||
{
|
||||
wlan_adapter *adapter = priv->adapter;
|
||||
struct tx_radiotap_hdr *radiotap_hdr;
|
||||
u32 status = adapter->eventcause;
|
||||
int txfail;
|
||||
int try_count;
|
||||
|
||||
if (adapter->radiomode != WLAN_RADIOMODE_RADIOTAP ||
|
||||
adapter->currenttxskb == NULL)
|
||||
return;
|
||||
|
||||
radiotap_hdr = (struct tx_radiotap_hdr *)adapter->currenttxskb->data;
|
||||
|
||||
if ((adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
|
||||
lbs_dbg_hex("TX feedback: ", (u8 *) radiotap_hdr,
|
||||
min_t(unsigned int, adapter->currenttxskb->len, 100));
|
||||
|
||||
txfail = (status >> 24);
|
||||
|
||||
#if 0
|
||||
/* The version of roofnet that we've tested does not use this yet
|
||||
* But it may be used in the future.
|
||||
*/
|
||||
if (txfail)
|
||||
radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
|
||||
#endif
|
||||
try_count = (status >> 16) & 0xff;
|
||||
radiotap_hdr->data_retries = (try_count) ?
|
||||
(1 + adapter->txretrycount - try_count) : 0;
|
||||
libertas_upload_rx_packet(priv, adapter->currenttxskb);
|
||||
adapter->currenttxskb = NULL;
|
||||
priv->adapter->TxLockFlag = 0;
|
||||
if (priv->adapter->connect_status == libertas_connected)
|
||||
netif_wake_queue(priv->wlan_dev.netdev);
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
/**
|
||||
* This header file contains definition for global types
|
||||
*/
|
||||
#ifndef _WLAN_TYPES_
|
||||
#define _WLAN_TYPES_
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
/** IEEE type definitions */
|
||||
enum ieeetypes_elementid {
|
||||
SSID = 0,
|
||||
SUPPORTED_RATES,
|
||||
FH_PARAM_SET,
|
||||
DS_PARAM_SET,
|
||||
CF_PARAM_SET,
|
||||
TIM,
|
||||
IBSS_PARAM_SET,
|
||||
COUNTRY_INFO = 7,
|
||||
|
||||
CHALLENGE_TEXT = 16,
|
||||
|
||||
EXTENDED_SUPPORTED_RATES = 50,
|
||||
|
||||
VENDOR_SPECIFIC_221 = 221,
|
||||
|
||||
WPA_IE = 221,
|
||||
WPA2_IE = 48,
|
||||
|
||||
EXTRA_IE = 133,
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define CAPINFO_MASK (~(0xda00))
|
||||
|
||||
struct ieeetypes_capinfo {
|
||||
u8 ess:1;
|
||||
u8 ibss:1;
|
||||
u8 cfpollable:1;
|
||||
u8 cfpollrqst:1;
|
||||
u8 privacy:1;
|
||||
u8 shortpreamble:1;
|
||||
u8 pbcc:1;
|
||||
u8 chanagility:1;
|
||||
u8 spectrummgmt:1;
|
||||
u8 rsrvd3:1;
|
||||
u8 shortslottime:1;
|
||||
u8 apsd:1;
|
||||
u8 rsvrd2:1;
|
||||
u8 dsssofdm:1;
|
||||
u8 rsrvd1:2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieeetypes_cfparamset {
|
||||
u8 elementid;
|
||||
u8 len;
|
||||
u8 cfpcnt;
|
||||
u8 cfpperiod;
|
||||
u16 cfpmaxduration;
|
||||
u16 cfpdurationremaining;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct ieeetypes_ibssparamset {
|
||||
u8 elementid;
|
||||
u8 len;
|
||||
u16 atimwindow;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
union IEEEtypes_ssparamset {
|
||||
struct ieeetypes_cfparamset cfparamset;
|
||||
struct ieeetypes_ibssparamset ibssparamset;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieeetypes_fhparamset {
|
||||
u8 elementid;
|
||||
u8 len;
|
||||
u16 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 {
|
||||
struct ieeetypes_capinfo capability;
|
||||
u16 statuscode;
|
||||
u16 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 {
|
||||
u16 type;
|
||||
u16 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 {
|
||||
u8 passivescan:1;
|
||||
u8 disablechanfilt:1;
|
||||
u8 reserved_2_7:6;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct chanscanparamset {
|
||||
u8 radiotype;
|
||||
u8 channumber;
|
||||
struct chanscanmode chanscanmode;
|
||||
u16 minscantime;
|
||||
u16 maxscantime;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_chanlistparamset {
|
||||
struct mrvlietypesheader header;
|
||||
struct chanscanparamset chanscanparam[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cfparamset {
|
||||
u8 cfpcnt;
|
||||
u8 cfpperiod;
|
||||
u16 cfpmaxduration;
|
||||
u16 cfpdurationremaining;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ibssparamset {
|
||||
u16 atimwindow;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_ssparamset {
|
||||
struct mrvlietypesheader header;
|
||||
union {
|
||||
struct cfparamset cfparamset[1];
|
||||
struct ibssparamset ibssparamset[1];
|
||||
} cf_ibss;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct fhparamset {
|
||||
u16 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));
|
||||
|
||||
struct mrvlietypes_rssithreshold {
|
||||
struct mrvlietypesheader header;
|
||||
u8 rssivalue;
|
||||
u8 rssifreq;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_snrthreshold {
|
||||
struct mrvlietypesheader header;
|
||||
u8 snrvalue;
|
||||
u8 snrfreq;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_failurecount {
|
||||
struct mrvlietypesheader header;
|
||||
u8 failvalue;
|
||||
u8 Failfreq;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_beaconsmissed {
|
||||
struct mrvlietypesheader header;
|
||||
u8 beaconmissed;
|
||||
u8 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_numprobes {
|
||||
struct mrvlietypesheader header;
|
||||
u16 numprobes;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_bcastprobe {
|
||||
struct mrvlietypesheader header;
|
||||
u16 bcastprobe;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvlietypes_numssidprobe {
|
||||
struct mrvlietypesheader header;
|
||||
u16 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));
|
||||
|
||||
#endif /* _WLAN_TYPES_ */
|
|
@ -0,0 +1,8 @@
|
|||
#define DRIVER_RELEASE_VERSION "320.p0"
|
||||
const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
|
||||
#ifdef DEBUG
|
||||
"-dbg"
|
||||
#endif
|
||||
"";
|
||||
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
* This file contains definition for IOCTL call.
|
||||
*/
|
||||
#ifndef _WLAN_WEXT_H_
|
||||
#define _WLAN_WEXT_H_
|
||||
|
||||
#define SUBCMD_OFFSET 4
|
||||
#define SUBCMD_DATA(x) *((int *)(x->u.name + SUBCMD_OFFSET))
|
||||
|
||||
/** PRIVATE CMD ID */
|
||||
#define WLANIOCTL SIOCIWFIRSTPRIV
|
||||
|
||||
#define WLANSETWPAIE (WLANIOCTL + 0)
|
||||
|
||||
#define WLAN_SETINT_GETINT (WLANIOCTL + 7)
|
||||
#define WLANNF 1
|
||||
#define WLANRSSI 2
|
||||
#define WLANENABLE11D 5
|
||||
#define WLANADHOCGRATE 6
|
||||
#define WLAN_SUBCMD_SET_PRESCAN 11
|
||||
|
||||
#define WLAN_SETNONE_GETNONE (WLANIOCTL + 8)
|
||||
#define WLANDEAUTH 1
|
||||
#define WLANRADIOON 2
|
||||
#define WLANRADIOOFF 3
|
||||
#define WLANREMOVEADHOCAES 4
|
||||
#define WLANADHOCSTOP 5
|
||||
#define WLANCIPHERTEST 6
|
||||
#define WLANCRYPTOTEST 7
|
||||
|
||||
#define WLANWLANIDLEON 10
|
||||
#define WLANWLANIDLEOFF 11
|
||||
#define WLAN_SUBCMD_BT_RESET 13
|
||||
#define WLAN_SUBCMD_FWT_RESET 14
|
||||
|
||||
#define WLANGETLOG (WLANIOCTL + 9)
|
||||
#define GETLOG_BUFSIZE 300
|
||||
|
||||
#define WLANSCAN_TYPE (WLANIOCTL + 11)
|
||||
|
||||
#define WLAN_SETNONE_GETONEINT (WLANIOCTL + 15)
|
||||
#define WLANGETREGION 1
|
||||
#define WLAN_GET_LISTEN_INTERVAL 2
|
||||
#define WLAN_GET_MULTIPLE_DTIM 3
|
||||
#define WLAN_GET_TX_RATE 4
|
||||
#define WLANGETBCNAVG 5
|
||||
|
||||
#define WLAN_GET_LINKMODE 6
|
||||
#define WLAN_GET_RADIOMODE 7
|
||||
#define WLAN_GET_DEBUGMODE 8
|
||||
#define WLAN_SUBCMD_FWT_CLEANUP 15
|
||||
#define WLAN_SUBCMD_FWT_TIME 16
|
||||
#define WLAN_SUBCMD_MESH_GET_TTL 17
|
||||
|
||||
#define WLANREGCFRDWR (WLANIOCTL + 18)
|
||||
|
||||
#define WLAN_SETNONE_GETTWELVE_CHAR (WLANIOCTL + 19)
|
||||
#define WLAN_SUBCMD_GETRXANTENNA 1
|
||||
#define WLAN_SUBCMD_GETTXANTENNA 2
|
||||
#define WLAN_GET_TSF 3
|
||||
|
||||
#define WLAN_SETNONE_GETWORDCHAR (WLANIOCTL + 21)
|
||||
#define WLANGETADHOCAES 1
|
||||
|
||||
#define WLAN_SETONEINT_GETONEINT (WLANIOCTL + 23)
|
||||
#define WLAN_BEACON_INTERVAL 1
|
||||
#define WLAN_LISTENINTRVL 4
|
||||
|
||||
#define WLAN_TXCONTROL 6
|
||||
#define WLAN_NULLPKTINTERVAL 7
|
||||
|
||||
#define WLAN_SETONEINT_GETNONE (WLANIOCTL + 24)
|
||||
#define WLAN_SUBCMD_SETRXANTENNA 1
|
||||
#define WLAN_SUBCMD_SETTXANTENNA 2
|
||||
#define WLANSETAUTHALG 5
|
||||
#define WLANSET8021XAUTHALG 6
|
||||
#define WLANSETENCRYPTIONMODE 7
|
||||
#define WLANSETREGION 8
|
||||
#define WLAN_SET_LISTEN_INTERVAL 9
|
||||
|
||||
#define WLAN_SET_MULTIPLE_DTIM 10
|
||||
#define WLAN_SET_ATIM_WINDOW 11
|
||||
#define WLANSETBCNAVG 13
|
||||
#define WLANSETDATAAVG 14
|
||||
#define WLAN_SET_LINKMODE 15
|
||||
#define WLAN_SET_RADIOMODE 16
|
||||
#define WLAN_SET_DEBUGMODE 17
|
||||
#define WLAN_SUBCMD_MESH_SET_TTL 18
|
||||
|
||||
#define WLAN_SET128CHAR_GET128CHAR (WLANIOCTL + 25)
|
||||
#define WLANSCAN_MODE 6
|
||||
|
||||
#define WLAN_GET_ADHOC_STATUS 9
|
||||
|
||||
#define WLAN_SUBCMD_BT_ADD 18
|
||||
#define WLAN_SUBCMD_BT_DEL 19
|
||||
#define WLAN_SUBCMD_BT_LIST 20
|
||||
#define WLAN_SUBCMD_FWT_ADD 21
|
||||
#define WLAN_SUBCMD_FWT_DEL 22
|
||||
#define WLAN_SUBCMD_FWT_LOOKUP 23
|
||||
#define WLAN_SUBCMD_FWT_LIST_NEIGHBOR 24
|
||||
#define WLAN_SUBCMD_FWT_LIST 25
|
||||
#define WLAN_SUBCMD_FWT_LIST_ROUTE 26
|
||||
|
||||
#define WLAN_SET_GET_SIXTEEN_INT (WLANIOCTL + 29)
|
||||
#define WLAN_TPCCFG 1
|
||||
#define WLAN_POWERCFG 2
|
||||
|
||||
#define WLAN_AUTO_FREQ_SET 3
|
||||
#define WLAN_AUTO_FREQ_GET 4
|
||||
#define WLAN_LED_GPIO_CTRL 5
|
||||
#define WLAN_SCANPROBES 6
|
||||
#define WLAN_ADAPT_RATESET 8
|
||||
#define WLAN_INACTIVITY_TIMEOUT 9
|
||||
#define WLANSNR 10
|
||||
#define WLAN_GET_RATE 11
|
||||
#define WLAN_GET_RXINFO 12
|
||||
|
||||
#define WLANCMD52RDWR (WLANIOCTL + 30)
|
||||
#define WLANCMD53RDWR (WLANIOCTL + 31)
|
||||
#define CMD53BUFLEN 32
|
||||
|
||||
#define REG_MAC 0x19
|
||||
#define REG_BBP 0x1a
|
||||
#define REG_RF 0x1b
|
||||
#define REG_EEPROM 0x59
|
||||
#define WLAN_LINKMODE_802_3 0
|
||||
#define WLAN_LINKMODE_802_11 2
|
||||
#define WLAN_RADIOMODE_NONE 0
|
||||
#define WLAN_RADIOMODE_RADIOTAP 2
|
||||
|
||||
/** wlan_ioctl_regrdwr */
|
||||
struct wlan_ioctl_regrdwr {
|
||||
/** Which register to access */
|
||||
u16 whichreg;
|
||||
/** Read or Write */
|
||||
u16 action;
|
||||
u32 offset;
|
||||
u16 NOB;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
extern struct iw_handler_def libertas_handler_def;
|
||||
int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int i);
|
||||
int wlan_radio_ioctl(wlan_private * priv, u8 option);
|
||||
|
||||
#endif /* _WLAN_WEXT_H_ */
|
|
@ -168,6 +168,23 @@ struct ieee80211_radiotap_header {
|
|||
* Unitless indication of the Rx/Tx antenna for this packet.
|
||||
* The first antenna is antenna 0.
|
||||
*
|
||||
* IEEE80211_RADIOTAP_RX_FLAGS u_int16_t bitmap
|
||||
*
|
||||
* Properties of received frames. See flags defined below.
|
||||
*
|
||||
* IEEE80211_RADIOTAP_TX_FLAGS u_int16_t bitmap
|
||||
*
|
||||
* Properties of transmitted frames. See flags defined below.
|
||||
*
|
||||
* IEEE80211_RADIOTAP_RTS_RETRIES u_int8_t data
|
||||
*
|
||||
* Number of rts retries a transmitted frame used.
|
||||
*
|
||||
* IEEE80211_RADIOTAP_DATA_RETRIES u_int8_t data
|
||||
*
|
||||
* Number of unicast retries a transmitted frame used.
|
||||
*
|
||||
*
|
||||
* IEEE80211_RADIOTAP_FCS u32 data
|
||||
*
|
||||
* FCS from frame in network byte order.
|
||||
|
@ -187,7 +204,11 @@ enum ieee80211_radiotap_type {
|
|||
IEEE80211_RADIOTAP_ANTENNA = 11,
|
||||
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
|
||||
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
|
||||
IEEE80211_RADIOTAP_EXT = 31,
|
||||
IEEE80211_RADIOTAP_RX_FLAGS = 14,
|
||||
IEEE80211_RADIOTAP_TX_FLAGS = 15,
|
||||
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
|
||||
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
|
||||
IEEE80211_RADIOTAP_EXT = 31
|
||||
};
|
||||
|
||||
/* Channel flags. */
|
||||
|
@ -219,6 +240,14 @@ enum ieee80211_radiotap_type {
|
|||
* 802.11 header and payload
|
||||
* (to 32-bit boundary)
|
||||
*/
|
||||
/* For IEEE80211_RADIOTAP_RX_FLAGS */
|
||||
#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
|
||||
|
||||
/* For IEEE80211_RADIOTAP_TX_FLAGS */
|
||||
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
|
||||
* retries */
|
||||
#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
|
||||
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
|
||||
|
||||
/* Ugly macro to convert literal channel numbers into their mhz equivalents
|
||||
* There are certianly some conditions that will break this (like feeding it '30')
|
||||
|
|
Загрузка…
Ссылка в новой задаче