[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:
Marcelo Tosatti 2007-02-10 12:25:27 -02:00 коммит произвёл Jeff Garzik
Родитель 35c3404efa
Коммит 876c9d3aeb
40 изменённых файлов: 22351 добавлений и 1 удалений

Просмотреть файл

@ -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, &regctrl, 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,
&regctrl);
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')