2009-10-14 14:53:43

by Holger Schurig

[permalink] [raw]
Subject: [WIP, RFC] libertas: allow scanning via "iw"

Do not apply, but please look at the code and comment harshly :-)



Things that work in some basic way:

* iw eth1 scan / scan trigger / scan dump, including
passive-scanning, scan-for-ssid, scan-on-specified-freq

* iw eth1 connect SSID 2437 00:11:22:33:44:55 key 0:99999
(the mentions MAC address must be in the bss list that you
get via "iw scan dump")

* ./wpa_supplicant -D nl80211 with
network={
ssid="SSID"
key_mgmt=NONE
wep_key0="99999"
wep_tx_keyidx=0
scan_ssid=1
scan_freq=2437
}

* "iw link" gives basic output




Now, that's the nice stuff. Now to the ugly stuff:

* There are some open points, all marked as TODO

* scan.{h,c}, wext.{h,c}, 11d.{h,c}, assoc.{h,c} are just
disabled. The will go for good. But for now I kept them
-> easier grepping

* no support for WPA / WPA2 yet

* no support for IBSS yet

* no support for MESH yet (and won't be implemented by me)

* no support for monitor mode yet

* formula for calculation of dBm migth be wrong

* no AUTH TLV for new libertas' firmware

* still dead code in the file (the .auth/.deauth, .assoc/.diassoc approach)

* no clue what IE i should send in cfg80211_connect_result()

* still some fields in "struct libertas_private" that I want to get rid of,
e.g. priv->connect_status. I think I can re-use something from struct
wireless_dev for that?

* "iw eth1 connect SSID" doesn't work, you HAVE to specify the BSSID of an
access-point. This is because of a impedance mismatch of cfg80211's
.connect/.disconnect API and libertas firmware.

Ah, and cfg80211's .auth/.deauth .assoc/.disassoc API doesn't suit the
libertas firmware that much better.

* no short preamble support yet

* no clue which IE to send in cfg80211_disconnected()

* WEP: no support for tx key != rx key, or keys != 1 yet. And no support
to delete keys yet. Or to get them back.

* no support to get TX rate out of the firmware and into "iw link".



Signed-off-by: Holger Schurig <[email protected]>

Do not apply, but please look at the code and comment harshly :-)

--- linux-wl.orig/drivers/net/wireless/libertas/cfg.c
+++ linux-wl/drivers/net/wireless/libertas/cfg.c
@@ -6,10 +6,18 @@
*
*/

+#include <linux/ieee80211.h>
+#include <linux/sched.h>
+#include <net/lib80211.h>
#include <net/cfg80211.h>
+#include <asm/unaligned.h>

#include "cfg.h"
#include "cmd.h"
+#include "host.h"
+#include "decl.h"
+
+#define USE_CONNECT


#define CHAN2G(_channel, _freq, _flags) { \
@@ -38,26 +46,27 @@
CHAN2G(14, 2484, 0),
};

-#define RATETAB_ENT(_rate, _rateid, _flags) { \
- .bitrate = (_rate), \
- .hw_value = (_rateid), \
- .flags = (_flags), \
+#define RATETAB_ENT(_rate, _hw_value, _flags) { \
+ .bitrate = (_rate), \
+ .hw_value = (_hw_value), \
+ .flags = (_flags), \
}


+/* Table 6 in section 3.2.1.1 */
static struct ieee80211_rate lbs_rates[] = {
- RATETAB_ENT(10, 0x1, 0),
- RATETAB_ENT(20, 0x2, 0),
- RATETAB_ENT(55, 0x4, 0),
- RATETAB_ENT(110, 0x8, 0),
- RATETAB_ENT(60, 0x10, 0),
- RATETAB_ENT(90, 0x20, 0),
- RATETAB_ENT(120, 0x40, 0),
- RATETAB_ENT(180, 0x80, 0),
- RATETAB_ENT(240, 0x100, 0),
- RATETAB_ENT(360, 0x200, 0),
- RATETAB_ENT(480, 0x400, 0),
- RATETAB_ENT(540, 0x800, 0),
+ RATETAB_ENT(10, 0, 0),
+ RATETAB_ENT(20, 1, 0),
+ RATETAB_ENT(55, 2, 0),
+ RATETAB_ENT(110, 3, 0),
+ RATETAB_ENT(60, 9, 0),
+ RATETAB_ENT(90, 6, 0),
+ RATETAB_ENT(120, 7, 0),
+ RATETAB_ENT(180, 8, 0),
+ RATETAB_ENT(240, 9, 0),
+ RATETAB_ENT(360, 10, 0),
+ RATETAB_ENT(480, 11, 0),
+ RATETAB_ENT(540, 12, 0),
};

static struct ieee80211_supported_band lbs_band_2ghz = {
@@ -71,25 +80,244 @@
static const u32 cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP40,
WLAN_CIPHER_SUITE_WEP104,
- WLAN_CIPHER_SUITE_TKIP,
- WLAN_CIPHER_SUITE_CCMP,
+//TODO WLAN_CIPHER_SUITE_TKIP,
+//TODO WLAN_CIPHER_SUITE_CCMP,
};

+/* Time to stay on the channel */
+#define LBS_SCAN_DWELL_PASSIVE 100
+#define LBS_SCAN_DWELL_ACTIVE 40
+
+
+
+/***************************************************************************
+ * TLV utility functions
+ */
+
+
+/*
+ * Add ssid TLV of the form:
+ *
+ * TLV-ID SSID 00 00
+ * length 06 00
+ * ssid 4d 4e 54 45 53 54
+ */
+#define LBS_MAX_SSID_TLV_SIZE \
+ (sizeof(struct mrvl_ie_header) \
+ + IEEE80211_MAX_SSID_LEN)
+
+static int lbs_add_ssid_tlv(u8 *tlv, const u8 *ssid, int ssid_len)
+{
+ struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
+
+ ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
+ ssid_tlv->header.len = cpu_to_le16(ssid_len);
+ memcpy(ssid_tlv->ssid, ssid, ssid_len);
+ return sizeof(ssid_tlv->header) + ssid_len;
+}
+
+
+/*
+ * Add channel list TLV of the form:
+ *
+ * TLV-ID CHANLIST 01 01
+ * length 0e 00
+ * channel 00 01 00 00 00 64 00
+ * radio type 00
+ * channel 01
+ * scan type 00
+ * min scan time 00 00
+ * max scan time 64 00
+ * channel 2 00 02 00 00 00 64 00
+ *
+ * It adds the channel from priv->scan_channel to the TLV. Actual channel
+ * data comes from priv->wiphy->channels. This TLV is described in section
+ * 8.4.2
+ */
+#define LBS_MAX_CHANNEL_LIST_TLV_SIZE \
+ (sizeof(struct mrvl_ie_header) \
+ + (LBS_SCAN_BEFORE_NAP * sizeof(struct chanscanparamset)))
+
+static int lbs_add_channel_list_tlv(struct lbs_private *priv, u8 *tlv,
+ int last_channel, int active_scan)
+{
+ int chanscanparamsize = sizeof(struct chanscanparamset) *
+ (last_channel - priv->scan_channel);
+
+ struct mrvl_ie_header *header = (void *) tlv;
+
+ header->type = cpu_to_le16(TLV_TYPE_CHANLIST);
+ header->len = cpu_to_le16(chanscanparamsize);
+ tlv += sizeof(struct mrvl_ie_header);
+
+ lbs_deb_scan("scan channels %d to %d\n", priv->scan_channel,
+ last_channel);
+ memset(tlv, 0, chanscanparamsize);
+
+ while (priv->scan_channel < last_channel) {
+ struct chanscanparamset *param = (void *) tlv;
+
+ param->radiotype = CMD_SCAN_RADIO_TYPE_BG;
+ param->channumber =
+ priv->scan_req->channels[priv->scan_channel]->hw_value;
+ if (active_scan) {
+ param->maxscantime = cpu_to_le16(LBS_SCAN_DWELL_ACTIVE);
+ } else {
+ param->chanscanmode.passivescan = 1;
+ param->maxscantime = cpu_to_le16(LBS_SCAN_DWELL_PASSIVE);
+ }
+ tlv += sizeof(struct chanscanparamset);
+ priv->scan_channel++;
+ }
+ return sizeof(struct mrvl_ie_header) + chanscanparamsize;
+}
+
+
+/*
+ * Add rates TLV of the form
+ *
+ * TLV-ID RATES 01 00
+ * length 0e 00
+ * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c
+ *
+ * The rates are in lbs_bg_rates[], but for the 802.11b
+ * rates the high bit is set. We add this TLV only because
+ * there's a firmware which otherwise doesn't report all
+ * APs in range.
+ */
+#define LBS_MAX_RATES_TLV_SIZE \
+ (sizeof(struct mrvl_ie_header) \
+ + (ARRAY_SIZE(lbs_rates)))
+
+/* Adds a TLV with all rates the hardware supports */
+static int lbs_add_supported_rates_tlv(u8 *tlv)
+{
+ int i;
+ struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
+
+ rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
+ tlv += sizeof(rate_tlv->header);
+ for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) {
+ *tlv = lbs_rates[i].bitrate / 5;
+ /* This code makes sure that the 802.11b rates (1 MBit/s, 2
+ MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set.
+ Note that the values are MBit/s * 2, to mark them as
+ basic rates so that the firmware likes it better */
+ if (*tlv == 0x02 || *tlv == 0x04 ||
+ *tlv == 0x0b || *tlv == 0x16)
+ *tlv |= 0x80;
+ tlv++;
+ }
+ rate_tlv->header.len = cpu_to_le16(i);
+ return sizeof(rate_tlv->header) + i;
+}
+
+
+/*
+ * Adds a TLV with all rates the hardware AND bss supports. Example:
+ *
+ * 01 00 TLV_TYPE_RATES
+ * 04 00 len
+ * 82 84 8b 96 rates
+ */
+static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss)
+{
+ struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
+ const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
+ int n;
+
+ rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
+ tlv += sizeof(rate_tlv->header);
+
+ if (!rates_eid) {
+ /* Fallback: add basic 802.11b rates */
+ *tlv++ = 0x82;
+ *tlv++ = 0x84;
+ *tlv++ = 0x8b;
+ *tlv++ = 0x96;
+ n = 4;
+ } else {
+ int hw, ap;
+ u8 ap_max = rates_eid[1];
+ n = 0;
+ for (hw=0; hw<ARRAY_SIZE(lbs_rates); hw++) {
+ u8 hw_rate = lbs_rates[hw].bitrate / 5;
+ for (ap=0; ap < ap_max; ap++) {
+ if (hw_rate == (rates_eid[ap+2] & 0x7f)) {
+ *tlv++ = rates_eid[ap+2];
+ n++;
+ }
+ }
+ }
+ }
+
+ rate_tlv->header.len = cpu_to_le16(n);
+ return sizeof(rate_tlv->header) + n;
+}
+
+
+/* Add channel TLV of the form
+ *
+ * 03 00 TLV_TYPE_PHY_DS
+ * 01 00 len
+ * 06 channel
+ */
+#define LBS_MAX_CHANNEL_TLV_SIZE \
+ sizeof(struct mrvl_ie_header)
+
+static int lbs_add_channel_tlv(u8 *tlv, u8 channel)
+{
+ struct mrvl_ie_ds_param_set *ds = (void *) tlv;
+
+ ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
+ ds->header.len = cpu_to_le16(sizeof(*ds)-sizeof(ds->header));
+ ds->channel = channel;
+ return sizeof(*ds);
+}
+
+
+/*
+ * Add (empty) CF param TLV of the form:
+ *
+ * 04 00 TLV_TYPE_CF
+ * 06 00 len
+ * 00 cfpcnt
+ * 00 cfpperiod
+ * 00 00 cfpmaxduration
+ * 00 00 cfpdurationremaining
+ */
+#define LBS_MAX_CF_PARAM_TLV_SIZE \
+ sizeof(struct mrvl_ie_header)
+
+static int lbs_add_cf_param_tlv(u8 *tlv)
+{
+ struct mrvl_ie_cf_param_set *cf = (void *)tlv;
+
+ cf->header.type = cpu_to_le16(TLV_TYPE_CF);
+ cf->header.len = cpu_to_le16(sizeof(*cf)-sizeof(cf->header));
+ return sizeof(*cf);
+}
+


+/***************************************************************************
+ * Set Channel
+ */
+
static int lbs_cfg_set_channel(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
+ struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type)
{
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = -ENOTSUPP;

- lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type);
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
+ channel->center_freq, channel_type);

if (channel_type != NL80211_CHAN_NO_HT)
goto out;

- ret = lbs_set_channel(priv, chan->hw_value);
+ ret = lbs_set_channel(priv, channel->hw_value);

out:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -98,9 +326,1091 @@



+/***************************************************************************
+ * Scanning
+ */
+
+/*
+ * When scanning, the firmware doesn't send a nul packet with the power-safe
+ * bit on to the AP. So we cannot stay away from our current channel too
+ * long, otherwise we loose data. So take a "nap" while scanning every other
+ * while.
+ */
+#define LBS_SCAN_BEFORE_NAP 4
+
+/*
+ * Our scan command contains a TLV, consting of a SSID TLV, a channel list
+ * TLV and a rates TLV. Determine the maximum size of them:
+ */
+
+/*
+ * When the firmware reports back a scan-result, it gives us an "u8 rssi",
+ * which isn't really an RSSI, as it becomes larger when moving away from
+ * the AP. Anyway, we need to convert that into mBm.
+ *
+ * TODO: check the formula. I know it's not correct, but it's the best I have
+ * so far.
+ */
+#define LBS_SCAN_RSSI_TO_MBM(rssi) \
+ ((-(int)rssi + 3)*100)
+
+
+static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *resp)
+{
+ struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
+ int bsssize;
+ const u8 *pos;
+ u16 nr_sets;
+ const u8 *tsfdesc;
+ int tsfsize;
+ int i;
+ int ret = -EILSEQ;
+
+ bsssize = get_unaligned_le16(&scanresp->bssdescriptsize);
+ nr_sets = le16_to_cpu(resp->size);
+
+ /* The general layout of the scan response is described in
+ * chapter 5.7.1. Basically we have a common part, then
+ * any number off BSS descriptor sections. Finally we have
+ * one data section with the same number of TSFs.
+ *
+ * cmd_ds_802_11_scan_rsp
+ * cmd_header
+ * pos_size
+ * nr_sets
+ * bssdesc 1
+ * bssid
+ * rssi
+ * timestamp
+ * intvl
+ * capa
+ * IEs
+ * bssdesc 2
+ * bssdesc n
+ * MrvlIEtypes_TsfFimestamp_t
+ * TSF for BSS 1
+ * TSF for BSS 2
+ * TSF for BSS n
+ */
+
+ pos = scanresp->bssdesc_and_tlvbuffer;
+
+ tsfdesc = pos + bsssize;
+ tsfsize = 4 + 8 * scanresp->nr_sets;
+
+ /* Validity check: we expect a Marvell-Local TLV */
+ i = get_unaligned_le16(tsfdesc);
+ tsfdesc += 2;
+ if (i != TLV_TYPE_TSFTIMESTAMP)
+ goto done;
+ /* Validity check: the TLV holds TSF values with 8 bytes each, so
+ * the size in the TLV must match the nr_sets value */
+ i = get_unaligned_le16(tsfdesc);
+ tsfdesc += 2;
+ if (i / 8 != scanresp->nr_sets)
+ goto done;
+
+ for (i = 0; i < scanresp->nr_sets; i++) {
+ const u8 *bssid;
+ const u8 *ie;
+ int left;
+ int ielen;
+ int rssi;
+ u16 intvl;
+ u16 capa;
+ int chan_no = -1;
+
+ int len = get_unaligned_le16(pos);
+ pos += 2;
+
+ /* BSSID */
+ bssid = pos;
+ pos += ETH_ALEN;
+ /* RSSI */
+ rssi = *pos++;
+ /* Packet time stamp */
+ pos += 8;
+ /* Beacon interval */
+ intvl = get_unaligned_le16(pos);
+ pos += 2;
+ /* Capabilities */
+ capa = get_unaligned_le16(pos);
+ pos += 2;
+
+ /* To find out the channel, we must parse the IEs */
+ ie = pos;
+ ielen = left = len - 6-1-8-2-2;
+ while (left >= 2) {
+ u8 id, elen;
+ id = *pos++;
+ elen = *pos++;
+ left -= 2;
+ if (elen > left || elen == 0)
+ goto done;
+ if (id == WLAN_EID_DS_PARAMS)
+ chan_no = *pos;
+ left -= elen;
+ pos += elen;
+ }
+
+ if (chan_no != -1) {
+ struct wiphy *wiphy = priv->wdev->wiphy;
+ int freq = ieee80211_channel_to_frequency(chan_no);
+ struct ieee80211_channel *channel =
+ ieee80211_get_channel(wiphy, freq);
+ if (channel ||
+ !(channel->flags & IEEE80211_CHAN_DISABLED))
+ cfg80211_inform_bss(wiphy, channel,
+ bssid, le64_to_cpu(*(__le64 *)tsfdesc),
+ capa, intvl, ie, ielen,
+ LBS_SCAN_RSSI_TO_MBM(rssi),
+ GFP_KERNEL);
+ }
+ tsfdesc += 8;
+ }
+ ret = 0;
+
+ done:
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+ return ret;
+}
+
+
+#define LBS_SCAN_MAX_CMD_SIZE \
+ (sizeof(struct cmd_ds_802_11_scan) \
+ + LBS_MAX_SSID_TLV_SIZE \
+ + LBS_MAX_CHANNEL_LIST_TLV_SIZE \
+ + LBS_MAX_RATES_TLV_SIZE)
+
+/*
+ * Assumes priv->scan_req is initialized and valid
+ * Assumes priv->scan_channel is initialized
+ */
+void lbs_cfg_scan_worker(struct work_struct *work)
+{
+ struct lbs_private *priv =
+ container_of(work, struct lbs_private, scan_work.work);
+ struct cmd_ds_802_11_scan *scan_cmd;
+ u8 *tlv; /* pointer into our current, growing TLV storage area */
+ int last_channel;
+ int running, carrier;
+ int mesh_running = false;
+ int mesh_carrier = false;
+
+ lbs_deb_enter(LBS_DEB_SCAN);
+
+ scan_cmd = kzalloc(LBS_SCAN_MAX_CMD_SIZE, GFP_KERNEL);
+ if (scan_cmd == NULL)
+ goto out_no_scan_cmd;
+
+ /* prepare fixed part of scan command */
+ scan_cmd->bsstype = CMD_BSS_TYPE_ANY;
+
+ /* stop network while we're away from our main channel */
+ running = !netif_queue_stopped(priv->dev);
+ carrier = netif_carrier_ok(priv->dev);
+ if (running)
+ netif_stop_queue(priv->dev);
+ if (carrier)
+ netif_carrier_off(priv->dev);
+ if (priv->mesh_dev) {
+ mesh_running = !netif_queue_stopped(priv->mesh_dev);
+ mesh_carrier = netif_carrier_ok(priv->mesh_dev);
+ if (mesh_running)
+ netif_stop_queue(priv->mesh_dev);
+ if (mesh_carrier)
+ netif_carrier_off(priv->mesh_dev);
+ }
+
+ /* prepare fixed part of scan command */
+ tlv = scan_cmd->tlvbuffer;
+
+ /* add SSID TLV */
+ if (priv->scan_req->n_ssids)
+ tlv += lbs_add_ssid_tlv(tlv,
+ priv->scan_req->ssids[0].ssid,
+ priv->scan_req->ssids[0].ssid_len);
+
+ /* add channel TLVs */
+ last_channel = priv->scan_channel + LBS_SCAN_BEFORE_NAP;
+ if (last_channel > priv->scan_req->n_channels)
+ last_channel = priv->scan_req->n_channels;
+ tlv += lbs_add_channel_list_tlv(priv, tlv, last_channel,
+ priv->scan_req->n_ssids);
+
+ /* add rates TLV */
+ tlv += lbs_add_supported_rates_tlv(tlv);
+
+ if (priv->scan_channel < priv->scan_req->n_channels) {
+ lbs_deb_scan("reschedule scan\n");
+ cancel_delayed_work(&priv->scan_work);
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+ msecs_to_jiffies(300));
+ }
+
+ /* This is the final data we are about to send */
+ scan_cmd->hdr.size = cpu_to_le16(tlv - (u8 *)scan_cmd);
+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
+ sizeof(*scan_cmd));
+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
+ tlv - scan_cmd->tlvbuffer);
+
+ __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
+ le16_to_cpu(scan_cmd->hdr.size),
+ lbs_ret_scan, 0);
+
+ if (priv->scan_channel >= priv->scan_req->n_channels) {
+ /* Mark scan done */
+ cfg80211_scan_done(priv->scan_req, false);
+ priv->scan_req = NULL;
+ }
+
+ /* Restart network */
+ if (carrier)
+ netif_carrier_on(priv->dev);
+ if (running && !priv->tx_pending_len)
+ netif_wake_queue(priv->dev);
+ if (mesh_carrier)
+ netif_carrier_on(priv->mesh_dev);
+ if (mesh_running && !priv->tx_pending_len)
+ netif_wake_queue(priv->mesh_dev);
+
+ kfree(scan_cmd);
+
+ out_no_scan_cmd:
+ lbs_deb_leave(LBS_DEB_CFG80211);
+}
+
+
+static int lbs_cfg_scan(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_scan_request *request)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ if (priv->scan_req || delayed_work_pending(&priv->scan_work)) {
+ /* old scan request not yet processed */
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ lbs_deb_cfg80211("n_ssids %d, n_channels %d, ie_len %d\n",
+ request->n_ssids, request->n_channels, request->ie_len);
+
+ priv->scan_channel = 0;
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+ msecs_to_jiffies(50));
+
+ if (priv->surpriseremoved)
+ ret = -EIO;
+
+ priv->scan_req = request;
+
+ out:
+ lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+ return ret;
+}
+
+
+
+/***************************************************************************
+ * Connect/disconnect
+ */
+
+
+/*
+ * Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1
+ * in the firmware spec
+ */
+static int lbs_cfg80211_auth_to_lbs_auth(enum nl80211_auth_type auth_type)
+{
+ int ret = -ENOTSUPP;
+
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", auth_type);
+
+ switch(auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ ret = auth_type;
+ break;
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ ret = NL80211_AUTHTYPE_OPEN_SYSTEM;
+ break;
+ case NL80211_AUTHTYPE_NETWORK_EAP:
+ ret = 0x80;
+ break;
+ default:
+ /* silence compiler */
+ break;
+ }
+ lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+ return ret;
+}
+
+
+/*
+ * Create association request
+ *
+ * Sample request:
+ *
+ * 50 00 CMD_802_11_ASSOCIATE
+ * 34 00 length
+ * 18 00 sequence no.
+ * 00 00 return code
+ * 00 13 19 80 da 30 BSS id
+ * 11 00 capabilities
+ * 0a 00 listen interval
+ * 00 00 beacon interval
+ * 00 DTIM period
+ * ie IE data (up to 512 bytes)
+ */
+#define LBS_ASSOC_MAX_CMD_SIZE \
+ (sizeof(struct cmd_ds_802_11_associate) \
+ - 512 /* cmd_ds_802_11_associate.iebuf */ \
+ + LBS_MAX_SSID_TLV_SIZE \
+ + LBS_MAX_CHANNEL_TLV_SIZE \
+ + LBS_MAX_CF_PARAM_TLV_SIZE \
+ /* TODO: LBS_MAX_AUTH_TLV_SIZE */ \
+ /* TODO: WPA/WPA2 IE */)
+
+static int lbs_do_assoc(struct wiphy *wiphy,
+ struct cfg80211_bss *bss,
+ const u8 *ie, int ie_len,
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *))
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ struct cmd_ds_802_11_associate *cmd = kzalloc(LBS_ASSOC_MAX_CMD_SIZE, GFP_KERNEL);
+ const u8 *ssid_eid;
+ size_t len;
+ u8 *pos = &(cmd->iebuf[0]);
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ cmd->hdr.command = cpu_to_le16(CMD_802_11_ASSOCIATE);
+
+ /* Fill in static fields */
+ memcpy(cmd->bssid, bss->bssid, ETH_ALEN);
+ cmd->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
+ cmd->capability = cpu_to_le16(bss->capability);
+
+ /* add SSID TLV */
+ ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
+ if (ssid_eid)
+ pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]);
+ else
+ printk("##HS no SSID\n");
+
+ /* add DS param TLV */
+ if (bss->channel)
+ pos += lbs_add_channel_tlv(pos, bss->channel->hw_value);
+ else
+ printk("##HS no channel\n");
+
+ /* add (empty) CF param TLV */
+ pos += lbs_add_cf_param_tlv(pos);
+
+ /* add rates TLV */
+ pos += lbs_add_common_rates_tlv(pos, bss);
+
+ /* add auth type TLV */
+ if (priv->fwrelease >= 0x09000000) {
+ printk("##HS TODO authentication suites as TLV\n");
+ }
+
+ /* add WPA/WPA2 IEs */
+ if (ie && ie_len) {
+ //struct mrvl_ie_rsn_param_set *rsn = pos;
+ //rsn->header.len = cpu_to_le16(ie_len);
+ //memcpy(rsn->rsnie, ie, ie_len);
+ // pos += ie_len;
+ printk("##HS TODO need to copy %d bytes for IE\n", ie_len);
+ }
+
+ len = (sizeof(*cmd) - sizeof(cmd->iebuf)) +
+ (u16)(pos - (u8 *) &cmd->iebuf);
+ cmd->hdr.size = cpu_to_le16(len);
+
+ /* store for later use */
+ memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN);
+
+ __lbs_cmd_async(priv, CMD_802_11_ASSOCIATE,
+ &cmd->hdr, len,
+ callback, 0);
+
+ lbs_deb_leave(LBS_DEB_CFG80211);
+
+ done:
+ return ret;
+}
+
+
+
+#ifndef USE_CONNECT
+
+/*
+ * Sample response:
+ *
+ * 11 80 RSP_802_11_AUTHENTICATE
+ * 19 00 cmd_len
+ * 16 00 sequence no
+ * 00 00 result
+ * 00 13 19 80 da 30 BSS id
+ * 00 ignored
+ * 00 00 02 00 00 00 00 00 00 00 ignored
+ */
+static int lbs_cfg_ret_auth(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *resp)
+{
+ struct cmd_ds_802_11_authenticate *auth_resp = (void *)resp;
+ struct ieee80211_mgmt mgmt;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+
+ /* Fake a management frame */
+ memset(&mgmt, 0, sizeof(mgmt));
+ mgmt.frame_control = cpu_to_le16(0xb0);
+ memcpy(mgmt.bssid, auth_resp->bssid, ETH_ALEN);
+ memcpy(mgmt.sa, auth_resp->bssid, ETH_ALEN);
+ memcpy(mgmt.da, priv->current_addr, ETH_ALEN);
+ mgmt.u.auth.status_code = cpu_to_le16(auth_resp->authtype);
+ cfg80211_send_rx_auth(priv->dev, (u8*)&mgmt, sizeof(mgmt));
+
+ lbs_deb_leave(LBS_DEB_CFG80211);
+ return 0;
+}
+
+
+/*
+ * Sample command:
+ *
+ * 11 00 CMD_802_11_AUTHENTICATE
+ * 19 00 cmd length
+ * 16 00 sequence no.
+ * 00 00 result
+ * 00 13 19 80 da 30 BSS id
+ * 00 auth type
+ * 00 00 00 00 00 00 00 00 00 00 10 bytes reserved
+ */
+static int lbs_cfg_auth(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_auth_request *req)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ struct cmd_ds_802_11_authenticate cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ memcpy(cmd.bssid, req->bss->bssid, ETH_ALEN);
+ ret = lbs_cfg80211_auth_to_lbs_auth(req->auth_type);
+ if (ret < 0)
+ goto done;
+ cmd.authtype = ret;
+
+ __lbs_cmd_async(priv, CMD_802_11_AUTHENTICATE,
+ &cmd.hdr, sizeof(cmd),
+ lbs_cfg_ret_auth, 0);
+ ret = 0;
+
+ done:
+ lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+ return ret;
+}
+
+
+/*
+ * Sample response:
+ *
+ * 12 80 RSP_802_11_AUTHENTICATE
+ * 14 00 cmd_len
+ * 18 00 sequence no
+ * 00 00 result
+ * 11 00 capability
+ * 00 00 status code
+ * 01 c0 aid
+ * ie IEs
+ *
+ * Sample IE:
+ *
+ * 01 WLAN_EID_SSID
+ * 04 len
+ * 82 84 8b 96 SSID
+ */
+static int lbs_cfg_ret_assoc(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *resp)
+{
+ struct cmd_ds_802_11_associate_response *assoc_resp = (void *)resp;
+ struct ieee80211_mgmt mgmt;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* Fake a management frame */
+ memset(&mgmt, 0, sizeof(mgmt));
+ mgmt.frame_control = cpu_to_le16(0x10);
+ memcpy(mgmt.bssid, priv->assoc_bss, ETH_ALEN);
+ memcpy(mgmt.sa, priv->assoc_bss, ETH_ALEN);
+ memcpy(mgmt.da, priv->current_addr, ETH_ALEN);
+ mgmt.u.assoc_resp.capab_info = assoc_resp->capability;
+ mgmt.u.assoc_resp.status_code = assoc_resp->statuscode;
+ mgmt.u.assoc_resp.aid = assoc_resp->aid;
+ cfg80211_send_rx_assoc(priv->dev, (u8*)&mgmt, sizeof(mgmt));
+ //TODO append IE
+
+ return 0;
+}
+
+
+static int lbs_cfg_assoc(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_assoc_request *req)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ ret = lbs_set_channel(priv, req->bss->channel->hw_value);
+
+ /* TODO: radio control (long/short preamble)
+ *
+ * Sample request:
+ * 1c 00 0c 00 17 00 00 00 01 00 01 00
+ * Sample response
+ * 1c 80 0c 00 17 00 00 00 01 00 01 00
+ */
+
+ ret = lbs_do_assoc(wiphy, req->bss,
+ req->ie, req->ie_len,
+ lbs_cfg_ret_assoc);
+
+ lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+ return ret;
+}
+
+
+static int lbs_cfg_ret_deauth(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *resp)
+{
+ struct cmd_ds_802_11_deauthenticate *deauth_resp = (void *)resp;
+ struct ieee80211_mgmt mgmt;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* Fake a management frame */
+ memset(&mgmt, 0, sizeof(mgmt));
+ mgmt.frame_control = cpu_to_le16(0xc0);
+ memcpy(mgmt.bssid, deauth_resp->macaddr, ETH_ALEN);
+ /* Note: .sa / .da swapped */
+ memcpy(mgmt.da, deauth_resp->macaddr, ETH_ALEN);
+ memcpy(mgmt.sa, priv->current_addr, ETH_ALEN);
+ mgmt.u.deauth.reason_code = cpu_to_le16(priv->disassoc_reason);
+ if (dummy)
+ __cfg80211_send_deauth(priv->dev, (u8 *)&mgmt, sizeof(mgmt));
+ else
+ cfg80211_send_deauth(priv->dev, (u8 *)&mgmt, sizeof(mgmt));
+
+ lbs_deb_leave(LBS_DEB_CFG80211);
+ return 0;
+}
+
+
+static int lbs_cfg_deauth(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_deauth_request *req,
+ void *cookie)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ struct cmd_ds_802_11_deauthenticate cmd;
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ memcpy(cmd.macaddr, &req->bss->bssid, ETH_ALEN);
+ cmd.reasoncode = cpu_to_le16(req->reason_code);
+ priv->disassoc_reason = req->reason_code;
+
+ __lbs_cmd_async(priv, CMD_802_11_DEAUTHENTICATE,
+ &cmd.hdr, sizeof(cmd),
+ lbs_cfg_ret_deauth, 0);
+
+ return 0;
+}
+
+
+static int lbs_cfg_disassoc(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_disassoc_request *req,
+ void *cookie)
+{
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* TODO The firmware doesn't have a disassociate command */
+
+ lbs_deb_leave(LBS_DEB_CFG80211);
+ return 0;
+}
+
+#endif
+
+
+
+#ifdef USE_CONNECT
+
+/*
+ * Set / Unset wep key, sample command:
+ *
+ * 13 00 command
+ * 50 00 size
+ * 07 00 sequence
+ * 00 00 result
+ * 02 00 action, here ACT_ADD
+ * 00 00 transmit key
+ * 01 type for key 1, here WEP40
+ * 00 00 00 types for keys 2 .. 4
+ * 39 39 39 39 39 00 00 00 00 key 1
+ * 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 key 2
+ * 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 key 3
+ * 00 00 00 00 00 00 00
+ * 00 00 00 00 00 00 00 00 00 key 4
+*/
+static int lbs_cfg_set_wep(struct lbs_private *priv,
+ u8 key_idx,
+ const u8 *key,
+ u8 key_len)
+{
+ struct cmd_ds_802_11_set_wep cmd;
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.keyindex = cpu_to_le16(key_idx);
+ if (key && key_len) {
+ cmd.action = cpu_to_le16(CMD_ACT_ADD);
+ cmd.keytype[key_idx] = key_len == 5 ? CMD_TYPE_WEP_40_BIT : CMD_TYPE_WEP_104_BIT;
+ memcpy(cmd.keymaterial[key_idx], key, key_len);
+ } else {
+ cmd.action = cpu_to_le16(CMD_ACT_REMOVE);
+ }
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
+
+ lbs_deb_leave(LBS_DEB_CFG80211);
+ return ret;
+}
+
+
+/*
+ * Sets the auth type (open, shared, etc) in the firmware. That
+ * we use CMD_802_11_AUTHENTICATE is misleading, this firmware
+ * command doesn't send an authentication frame at all, it just
+ * stores the auth_type.
+ *
+ *
+ * Sample command:
+ *
+ * 11 00 CMD_802_11_AUTHENTICATE
+ * 19 00 cmd length
+ * 16 00 sequence no.
+ * 00 00 result
+ * 00 13 19 80 da 30 BSS id
+ * 00 auth type
+ * 00 00 00 00 00 00 00 00 00 00 10 bytes reserved
+ */
+static int lbs_cfg_set_authtype(struct lbs_private *priv,
+ struct cfg80211_connect_params *sme)
+{
+ struct cmd_ds_802_11_authenticate cmd;
+ int ret;
+
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", sme->auth_type);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ if (sme->bssid)
+ memcpy(cmd.bssid, sme->bssid, ETH_ALEN);
+ /* convert auth_type */
+ ret = lbs_cfg80211_auth_to_lbs_auth(sme->auth_type);
+ if (ret < 0)
+ goto done;
+
+ cmd.authtype = ret;
+ ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
+
+ done:
+ lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+ return ret;
+}
+
+
+static int lbs_cfg_ret_connect(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *resp)
+{
+ struct cmd_ds_802_11_associate_response *assoc_resp = (void *)resp;
+ size_t resp_ie_len;
+ int status = le16_to_cpu(assoc_resp->statuscode);
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ lbs_deb_assoc("status %d, capability 0x%04x\n",
+ status,
+ le16_to_cpu(assoc_resp->capability));
+
+ resp_ie_len = le16_to_cpu(resp->size);
+ cfg80211_connect_result(priv->dev,
+ priv->assoc_bss,
+ NULL, 0, //TODO what IE should I copy here?
+ assoc_resp->iebuf, resp_ie_len,
+ status,
+ GFP_KERNEL);
+
+ if (status == 0) {
+ // TODO: get rid of priv->connect_status
+ priv->connect_status = LBS_CONNECTED;
+ netif_carrier_on(priv->dev);
+ if (!priv->tx_pending_len)
+ netif_tx_wake_all_queues(priv->dev);
+ }
+
+ lbs_deb_leave(LBS_DEB_CFG80211);
+ return 0;
+}
+
+
+static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ struct cfg80211_bss *bss;
+ int ret = 0;
+ u8 preamble = RADIO_PREAMBLE_LONG;
+ DECLARE_SSID_BUF(ssid);
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+
+ if (sme->ssid)
+ lbs_deb_assoc("ssid %s\n", print_ssid(ssid, sme->ssid, sme->ssid_len));
+ if (sme->bssid) {
+ bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
+ sme->ssid, sme->ssid_len,
+ WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+ } else {
+ /*
+ * Here we have an impedance mismatch. The firmware command
+ * CMD_802_11_ASSOCIATE always needs a BSSID, it cannot connect
+ * otherwise. However, for the connect-API of cfg80211 the bssid is
+ * purely optional. We don't get one, except the user specifies one
+ * on the "iw" command line.
+ *
+ * If we don't got one, we could initiate a scan and look for the
+ * best matching cfg80211_bss entry.
+ *
+ * Or, better yet, net/wireless/sme.c get's rewritten into
+ * something more generally useful.
+ */
+ printk("##HS TODO: search for a bss\n");
+ ret = -ENOTSUPP;
+ goto done;
+ }
+
+
+ if (!bss) {
+ lbs_deb_assoc("bss %pM not in scan results\n", sme->bssid);
+ ret = -ENOENT;
+ goto done;
+ }
+ printk("##HS bss %pM found in scan results\n", sme->bssid);
+
+ printk("##HS auth_type %d\n", sme->auth_type);
+ printk("##HS privacy %d\n", sme->privacy);
+ printk("##HS crypto wpa_version %d\n", sme->crypto.wpa_versions);
+ printk("##HS crypto cipher_group 0x%x\n", sme->crypto.cipher_group);
+ printk("##HS crypto n_ciphers_pairwise %d\n", sme->crypto.n_ciphers_pairwise);
+ printk("##HS crypto n_akm_suites %d\n", sme->crypto.n_akm_suites);
+ printk("##HS crypto control_port %d\n", sme->crypto.control_port);
+ printk("##HS key %p, key_len %d, key_idx %d\n", sme->key, sme->key_len, sme->key_idx);
+ printk("##HS ie %p, ie_len %d\n", sme->ie, sme->ie_len);
+ if (sme->ie && sme->ie_len)
+ lbs_deb_hex(LBS_DEB_CFG80211, "IE", sme->ie, sme->ie_len);
+
+ /* set authentication type (open, shared, etc) */
+ lbs_cfg_set_authtype(priv, sme);
+
+ /* TODO set short preamble */
+ lbs_set_radio(priv, preamble, 1);
+
+ ret = lbs_do_assoc(wiphy, bss,
+ sme->ie, sme->ie_len,
+ lbs_cfg_ret_connect);
+
+ if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
+ priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
+ lbs_cfg_set_wep(priv, sme->key_idx, sme->key, sme->key_len);
+ } else {
+ priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
+ }
+
+ /*
+ * Sample command:
+ *
+ * cmd 28 00 0c 00 08 00 00 00 0b 00 00 00
+ */
+ lbs_set_mac_control(priv);
+
+ // TODO enable/disable RSN
+
+
+ // set priv filter
+
+
+ /* iw eth1 connect MNHS
+ --------------------
+ ssid MNHS
+ auth_type 4
+ ie (null), ie_len 0
+ privacy 0
+ crypto wpa_version 0
+ crypto cipher_group 0
+ crypto n_ciphers_pairwise 0
+ crypto n_akm_suites 0
+ crypto control_port 0
+ key (null), key_len 0, key_idx 0
+
+ iw eth1 connect MNHS key 0:54321
+ --------------------------------
+ ssid MNHS
+ auth_type 4
+ ie (null), ie_len 0
+ privacy 1
+ crypto wpa_version 0
+ crypto cipher_group 1027073
+ crypto n_ciphers_pairwise 1
+ crypto n_akm_suites 0
+ crypto control_port 0
+ key f7b9ce78, key_len 5, key_idx 0
+ */
+
+
+ done:
+ lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+ return ret;
+}
+
+
+static int lbs_cfg_ret_disconnect(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *resp)
+{
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ cfg80211_disconnected(priv->dev,
+ priv->disassoc_reason,
+ NULL, 0, // TODO?
+ GFP_KERNEL);
+
+ lbs_deb_leave(LBS_DEB_CFG80211);
+ return 0;
+}
+
+
+static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ struct cmd_ds_802_11_deauthenticate cmd;
+
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
+
+ /* store for lbs_cfg_ret_disconnect() */
+ priv->disassoc_reason = reason_code;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ // Mildly ugly to use a locally store my own BSSID ...
+ memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
+ cmd.reasoncode = cpu_to_le16(reason_code);
+
+ __lbs_cmd_async(priv, CMD_802_11_DEAUTHENTICATE,
+ &cmd.hdr, sizeof(cmd),
+ lbs_cfg_ret_disconnect, 0);
+
+ return 0;
+}
+#endif
+
+
+static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index, const u8 *mac_addr,
+ struct key_params *params)
+{
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* TODO */
+
+ /*
+ * iw eth1 connect MNHS 2437 key 0:99999
+ * -------------------------------------
+ * key_index 0
+ * mac_addr (null)
+ * cipher 0xfac01
+ * keylen 5, seqlen 0
+ */
+
+ printk("##HS key_index %d\n", key_index);
+ printk("##HS mac_addr %pM\n", mac_addr);
+ printk("##HS cipher 0x%x\n", params->cipher);
+ printk("##HS keylen %d, seqlen %d\n", params->key_len, params->seq_len);
+
+ return 0;
+}
+
+
+static int lbs_cfg_set_default_key(struct wiphy *wiphy,
+ struct net_device *netdev,
+ u8 key_index)
+{
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* TODO */
+
+ /*
+ * iw eth1 connect MNHS 2437 key 0:99999
+ * -------------------------------------
+ * key_index 0
+ */
+
+ printk("##HS key_index %d\n", key_index);
+ return 0;
+}
+
+
+static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index, const u8 *mac_addr)
+{
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* TODO */
+
+ //printk("##HS key_index %d\n", key_index);
+ //printk("##HS mac_addr %pM\n", mac_addr);
+
+ return -ENOTSUPP;
+}
+
+
+static int lbs_cfg_get_key(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index, const u8 *mac_addr, void *cookie,
+ void (*callback)(void *cookie, struct key_params*))
+{
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* TODO */
+
+ //printk("##HS key_index %d\n", key_index);
+ //printk("##HS mac_addr %pM\n", mac_addr);
+ //printk("##HS cookie %p\n", cookie);
+
+ return -ENOTSUPP;
+}
+
+
+
+
+
+
+
+
+/***************************************************************************
+ */
+
+static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo)
+{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_CFG80211);
+
+ /* Get current RSSI */
+ {
+ struct cmd_ds_802_11_rssi cmd;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.n_or_snr = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
+ if (ret == 0) {
+ sinfo->signal = CAL_RSSI(le16_to_cpu(cmd.n_or_snr),
+ le16_to_cpu(cmd.nf));
+ sinfo->filled |= STATION_INFO_SIGNAL;
+ }
+ }
+
+#ifdef TODO
+ //My firmware doesn't execute this command
+
+ /* Get current TX rate */
+ {
+ struct cmd_tx_rate_query cmd;
+ int i;
+ u16 tx_rate;
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.tx_rate = 0;
+ ret = lbs_cmd_with_response(priv, CMD_802_11_TX_RATE_QUERY, &cmd);
+ if (ret == 0) {
+ tx_rate = le16_to_cpu(cmd.tx_rate);
+ //printk("##HS txrate %d\n", tx_rate);
+ for (i=0; i<ARRAY_SIZE(lbs_rates); i++) {
+ if (tx_rate == lbs_rates[i].hw_value) {
+ sinfo->txrate.legacy = lbs_rates[i].bitrate;
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+ break;
+ }
+ }
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+
+
+/***************************************************************************
+ * Initialization
+ */

static struct cfg80211_ops lbs_cfg80211_ops = {
.set_channel = lbs_cfg_set_channel,
+ .scan = lbs_cfg_scan,
+#ifdef USE_CONNECT
+ .connect = lbs_cfg_connect,
+ .disconnect = lbs_cfg_disconnect,
+#else
+ .auth = lbs_cfg_auth,
+ .deauth = lbs_cfg_deauth,
+ .assoc = lbs_cfg_assoc,
+ .disassoc = lbs_cfg_disassoc,
+#endif
+ .add_key = lbs_cfg_add_key,
+ .get_key = lbs_cfg_get_key,
+ .del_key = lbs_cfg_del_key,
+ .set_default_key = lbs_cfg_set_default_key,
+ .get_station = lbs_cfg_get_station,
};


--- linux-wl.orig/drivers/net/wireless/libertas/dev.h
+++ linux-wl/drivers/net/wireless/libertas/dev.h
@@ -10,6 +10,7 @@
#include <linux/wireless.h>
#include <linux/ethtool.h>
#include <linux/debugfs.h>
+#include <net/cfg80211.h>

#include "defs.h"
#include "hostcmd.h"
@@ -61,6 +62,7 @@
};

/** Current Basic Service Set State Structure */
+#ifdef TODO
struct current_bss_params {
/** bssid */
u8 bssid[ETH_ALEN];
@@ -75,6 +77,7 @@
/** zero-terminated array of supported data rates */
u8 rates[MAX_RATES + 1];
};
+#endif

/** sleep_params */
struct sleep_params {
@@ -100,13 +103,20 @@

/** Private structure for the MV device */
struct lbs_private {
+ /* cfg80211-related */
struct wireless_dev *wdev;
+ struct cfg80211_scan_request *scan_req;
+ u8 assoc_bss[ETH_ALEN];
+ u8 disassoc_reason;
+
int mesh_open;
int mesh_fw_ver;
int infra_open;
int mesh_autostart_enabled;

+#ifdef TODO
char name[DEV_NAME_LEN];
+#endif

void *card;
struct net_device *dev;
@@ -114,7 +124,9 @@
struct net_device *mesh_dev; /* Virtual device */
struct net_device *rtap_net_dev;

+#ifdef TODO
struct iw_statistics wstats;
+#endif
struct lbs_mesh_stats mstats;
struct dentry *debugfs_dir;
struct dentry *debugfs_debug;
@@ -159,7 +171,6 @@

/** Scanning */
struct delayed_work scan_work;
- struct delayed_work assoc_work;
struct work_struct sync_channel;
/* remember which channel was scanned last, != 0 if currently scanning */
int scan_channel;
@@ -214,8 +225,10 @@
/* Events sent from hardware to driver */
struct kfifo *event_fifo;

+#ifdef TODO
/* nickname */
u8 nodename[16];
+#endif

/** spin locks */
spinlock_t driver_lock;
@@ -226,8 +239,11 @@
int nr_retries;
int cmd_timed_out;

+#ifdef TODO
/** current ssid/bssid related parameters*/
struct current_bss_params curbssparams;
+#endif
+ u8 channel;

uint16_t mesh_tlv;
u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1];
@@ -236,10 +252,12 @@
/* IW_MODE_* */
u8 mode;

+#ifdef TODO
/* Scan results list */
struct list_head network_list;
struct list_head network_free_list;
struct bss_descriptor *networks;
+#endif

u16 beacon_period;
u8 beacon_enable;
@@ -254,10 +272,10 @@
u32 nr_of_multicastmacaddr;

/** 802.11 statistics */
-// struct cmd_DS_802_11_GET_STAT wlan802_11Stat;
-
uint16_t enablehwauto;
+#ifdef TODO
uint16_t ratebitmap;
+#endif

u8 txretrycount;

@@ -281,6 +299,7 @@
u32 psstate;
u8 needtowakeup;

+#ifdef TODO
struct assoc_request * pending_assoc_req;
struct assoc_request * in_progress_assoc_req;

@@ -313,16 +332,16 @@
u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
u16 nextSNRNF;
u16 numSNRNF;
+#endif

u8 radio_on;

/** data rate stuff */
u8 cur_rate;

- /** RF calibration data */
-
-#define MAX_REGION_CHANNEL_NUM 2
+#ifdef TODO
/** region channel data */
+#define MAX_REGION_CHANNEL_NUM 2
struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];

struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM];
@@ -333,6 +352,7 @@

/** FSM variable for 11d support */
u32 enable11d;
+#endif

/** MISCELLANEOUS */
struct lbs_offset_value offsetvalue;
@@ -346,6 +366,7 @@
/**
* @brief Structure used to store information for each beacon/probe response
*/
+#ifdef TODO
struct bss_descriptor {
u8 bssid[ETH_ALEN];

@@ -424,5 +445,6 @@
/* BSS to associate with for infrastructure of Ad-Hoc join */
struct bss_descriptor bss;
};
+#endif

#endif
--- linux-wl.orig/drivers/net/wireless/libertas/wext.c
+++ linux-wl/drivers/net/wireless/libertas/wext.c
@@ -16,9 +16,6 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
-#include "wext.h"
-#include "scan.h"
-#include "assoc.h"
#include "cmd.h"


@@ -2217,8 +2214,8 @@
(iw_handler) lbs_get_wap, /* SIOCGIWAP */
(iw_handler) NULL, /* SIOCSIWMLME */
(iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
- (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
- (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) NULL, /* SIOCSIWSCAN */
+ (iw_handler) NULL, /* SIOCGIWSCAN */
(iw_handler) lbs_set_essid, /* SIOCSIWESSID */
(iw_handler) lbs_get_essid, /* SIOCGIWESSID */
(iw_handler) lbs_set_nick, /* SIOCSIWNICKN */
@@ -2275,8 +2272,8 @@
(iw_handler) NULL, /* SIOCGIWAP */
(iw_handler) NULL, /* SIOCSIWMLME */
(iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
- (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
- (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) NULL, /* SIOCSIWSCAN */
+ (iw_handler) NULL, /* SIOCGIWSCAN */
(iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */
(iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */
(iw_handler) NULL, /* SIOCSIWNICKN */
--- linux-wl.orig/drivers/net/wireless/libertas/Makefile
+++ linux-wl/drivers/net/wireless/libertas/Makefile
@@ -1,5 +1,5 @@
-libertas-y += 11d.o
-libertas-y += assoc.o
+#libertas-y += 11d.o
+#libertas-y += assoc.o
libertas-y += cfg.o
libertas-y += cmd.o
libertas-y += cmdresp.o
@@ -8,9 +8,9 @@
libertas-y += main.o
libertas-y += persistcfg.o
libertas-y += rx.o
-libertas-y += scan.o
+#libertas-y += scan.o
libertas-y += tx.o
-libertas-y += wext.o
+#libertas-y += wext.o

usb8xxx-objs += if_usb.o
libertas_cs-objs += if_cs.o
--- linux-wl.orig/drivers/net/wireless/libertas/assoc.c
+++ linux-wl/drivers/net/wireless/libertas/assoc.c
@@ -6,10 +6,9 @@
#include <linux/if_arp.h>
#include <net/lib80211.h>

-#include "assoc.h"
#include "decl.h"
#include "host.h"
-#include "scan.h"
+#include "cfg.h"
#include "cmd.h"

static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
--- linux-wl.orig/drivers/net/wireless/libertas/main.c
+++ linux-wl/drivers/net/wireless/libertas/main.c
@@ -13,17 +13,17 @@
#include <linux/kfifo.h>
#include <linux/stddef.h>
#include <linux/ieee80211.h>
-#include <net/iw_handler.h>
+#ifdef TODO
+//#include <net/iw_handler.h>
+#endif
#include <net/cfg80211.h>

#include "host.h"
#include "decl.h"
#include "dev.h"
-#include "wext.h"
#include "cfg.h"
#include "debugfs.h"
-#include "scan.h"
-#include "assoc.h"
+#include "cfg.h"
#include "cmd.h"

#define DRIVER_RELEASE_VERSION "323.p0"
@@ -343,12 +343,14 @@
if (!priv->monitormode) {
if (priv->infra_open || priv->mesh_open)
return -EBUSY;
+#ifdef TODO
if (priv->mode == IW_MODE_INFRA)
lbs_cmd_80211_deauthenticate(priv,
priv->curbssparams.bssid,
WLAN_REASON_DEAUTH_LEAVING);
else if (priv->mode == IW_MODE_ADHOC)
lbs_adhoc_stop(priv);
+#endif
lbs_add_rtap(priv);
}
priv->monitormode = monitor_mode;
@@ -405,7 +407,7 @@
return count;
if (enable)
action = CMD_ACT_MESH_CONFIG_START;
- ret = lbs_mesh_config(priv, action, priv->curbssparams.channel);
+ ret = lbs_mesh_config(priv, action, priv->channel);
if (ret)
return ret;

@@ -559,8 +561,10 @@
firmware has crapped itself -- rather than just a very
busy medium. So send a harmless command, and if/when
_that_ times out, we'll kick it in the head. */
+#ifdef TODO
lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
0, 0, NULL);
+#endif

lbs_deb_leave(LBS_DEB_TX);
}
@@ -1135,14 +1139,21 @@
lbs_deb_leave(LBS_DEB_MAIN);
}

-
+#ifdef TODO
+#define MAX_NETWORK_COUNT 128
+#endif
static int lbs_init_adapter(struct lbs_private *priv)
{
+#ifdef TODO
size_t bufsize;
int i, ret = 0;
+#else
+ int ret = 0;
+#endif

lbs_deb_enter(LBS_DEB_MAIN);

+#ifdef TODO
/* Allocate buffer to store the BSSID list */
bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
priv->networks = kzalloc(bufsize, GFP_KERNEL);
@@ -1159,14 +1170,17 @@
list_add_tail(&priv->networks[i].list,
&priv->network_free_list);
}
+#endif

memset(priv->current_addr, 0xff, ETH_ALEN);

priv->connect_status = LBS_DISCONNECTED;
priv->mesh_connect_status = LBS_DISCONNECTED;
+#ifdef TODO
priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+#endif
priv->mode = IW_MODE_INFRA;
- priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
+ priv->channel = DEFAULT_AD_HOC_CHANNEL;
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
priv->radio_on = 1;
priv->enablehwauto = 1;
@@ -1223,8 +1237,10 @@
kfifo_free(priv->event_fifo);
del_timer(&priv->command_timer);
del_timer(&priv->auto_deepsleep_timer);
+#ifdef TODO
kfree(priv->networks);
priv->networks = NULL;
+#endif

lbs_deb_leave(LBS_DEB_MAIN);
}
@@ -1287,9 +1303,6 @@
dev->netdev_ops = &lbs_netdev_ops;
dev->watchdog_timeo = 5 * HZ;
dev->ethtool_ops = &lbs_ethtool_ops;
-#ifdef WIRELESS_EXT
- dev->wireless_handlers = &lbs_handler_def;
-#endif
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;


@@ -1313,8 +1326,7 @@
}

priv->work_thread = create_singlethread_workqueue("lbs_worker");
- INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
- INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
+ INIT_DELAYED_WORK(&priv->scan_work, lbs_cfg_scan_worker);
INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);

@@ -1347,7 +1359,9 @@
void lbs_remove_card(struct lbs_private *priv)
{
struct net_device *dev = priv->dev;
+#ifdef TODO
union iwreq_data wrqu;
+#endif

lbs_deb_enter(LBS_DEB_MAIN);

@@ -1357,7 +1371,6 @@
dev = priv->dev;

cancel_delayed_work_sync(&priv->scan_work);
- cancel_delayed_work_sync(&priv->assoc_work);
cancel_work_sync(&priv->mcast_work);

/* worker thread destruction blocks on the in-flight command which
@@ -1372,9 +1385,11 @@
lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
}

+#ifdef TODO
memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+#endif

if (priv->is_deep_sleep) {
priv->is_deep_sleep = 0;
@@ -1408,8 +1423,10 @@
if (ret)
goto done;

+#ifdef TODO
/* init 802.11d */
lbs_init_11d(priv);
+#endif

if (lbs_cfg_register(priv)) {
lbs_pr_err("cannot register device\n");
@@ -1437,10 +1454,10 @@

priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->curbssparams.channel)) {
+ priv->channel)) {
priv->mesh_tlv = TLV_TYPE_MESH_ID;
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->curbssparams.channel))
+ priv->channel))
priv->mesh_tlv = 0;
}
} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
@@ -1449,7 +1466,7 @@
*/
priv->mesh_tlv = TLV_TYPE_MESH_ID;
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
- priv->curbssparams.channel))
+ priv->channel))
priv->mesh_tlv = 0;
}
if (priv->mesh_tlv) {
@@ -1568,9 +1585,6 @@

SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);

-#ifdef WIRELESS_EXT
- mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
-#endif
mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
/* Register virtual mesh interface */
ret = register_netdev(mesh_dev);
@@ -1651,6 +1665,7 @@
return NULL;
}

+#ifdef TODO
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
{
int ret = 0;
@@ -1681,6 +1696,7 @@
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
+#endif

void lbs_queue_event(struct lbs_private *priv, u32 event)
{
--- linux-wl.orig/drivers/net/wireless/libertas/persistcfg.c
+++ linux-wl/drivers/net/wireless/libertas/persistcfg.c
@@ -9,10 +9,7 @@
#include "host.h"
#include "decl.h"
#include "dev.h"
-#include "wext.h"
#include "debugfs.h"
-#include "scan.h"
-#include "assoc.h"
#include "cmd.h"

static int mesh_get_default_parameters(struct device *dev,
--- linux-wl.orig/drivers/net/wireless/libertas/scan.c
+++ linux-wl/drivers/net/wireless/libertas/scan.c
@@ -3,6 +3,8 @@
*
* IOCTL handlers as well as command preperation and response routines
* for sending scan commands to the firmware.
+ *
+ * TODO: remove this file
*/
#include <linux/types.h>
#include <linux/kernel.h>
--- linux-wl.orig/drivers/net/wireless/libertas/scan.h
+++ linux-wl/drivers/net/wireless/libertas/scan.h
@@ -1,3 +1,6 @@
+#error don't include scan.h
+/* TODO: remove this file */
+
/**
* Interface for the wlan network scan routines
*
--- linux-wl.orig/drivers/net/wireless/libertas/11d.c
+++ linux-wl/drivers/net/wireless/libertas/11d.c
@@ -9,7 +9,6 @@
#include "decl.h"
#include "11d.h"
#include "dev.h"
-#include "wext.h"

#define TX_PWR_DEFAULT 10

@@ -43,6 +42,7 @@
{14, 2484, TX_PWR_DEFAULT}
};

+#ifdef TODO
static u8 lbs_region_2_code(u8 *region)
{
u8 i;
@@ -59,6 +59,7 @@
/* default is US */
return (region_code_mapping[0].code);
}
+#endif

static u8 *lbs_code_2_region(u8 code)
{
@@ -79,6 +80,7 @@
* @param nrchan number of channels
* @return the nrchan-th chan number
*/
+#ifdef TODO
static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
/*find the nrchan-th chan after the firstchan*/
{
@@ -106,6 +108,7 @@

return 0;
}
+#endif

/**
* @brief This function Checks if chan txpwr is learned from AP/IBSS
@@ -264,6 +267,7 @@
* @param chan chan
* @return TRUE;FALSE
*/
+#ifdef TODO
static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
{
struct chan_freq_power *cfp;
@@ -401,6 +405,7 @@
lbs_deb_enter(LBS_DEB_11D);
return 0;
}
+#endif

/**
* @brief This function calculates the scan type for channels
@@ -595,6 +600,7 @@
* @param priv pointer to struct lbs_private
* @return 0; -1
*/
+#ifdef TODO
int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
struct bss_descriptor * bss)
{
@@ -694,3 +700,4 @@
lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
return ret;
}
+#endif
--- linux-wl.orig/drivers/net/wireless/libertas/assoc.h
+++ linux-wl/drivers/net/wireless/libertas/assoc.h
@@ -1,3 +1,6 @@
+#error don't include wext.h
+/* TODO: remove this file */
+
/* Copyright (C) 2006, Red Hat, Inc. */

#ifndef _LBS_ASSOC_H_
--- linux-wl.orig/drivers/net/wireless/libertas/cmd.c
+++ linux-wl/drivers/net/wireless/libertas/cmd.c
@@ -3,17 +3,18 @@
* It prepares command and sends it to firmware when it is ready.
*/

-#include <net/iw_handler.h>
+#ifdef TODO
+//#include <net/iw_handler.h>
+#endif
#include <net/lib80211.h>
#include <linux/kfifo.h>
#include <linux/sched.h>
+
#include "host.h"
#include "hostcmd.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
-#include "assoc.h"
-#include "wext.h"
#include "cmd.h"

static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
@@ -187,6 +188,7 @@
if (priv->mesh_dev)
memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);

+#ifdef TODO
if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
ret = -1;
goto out;
@@ -196,6 +198,7 @@
ret = -1;
goto out;
}
+#endif

out:
lbs_deb_leave(LBS_DEB_CMD);
@@ -397,6 +400,7 @@
return ret;
}

+#ifdef TODO
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc)
{
@@ -587,6 +591,7 @@
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
+#endif

/**
* @brief Set an SNMP MIB value
@@ -815,7 +820,6 @@
cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
if (!ret && cmd_action == CMD_ACT_GET) {
- priv->ratebitmap = le16_to_cpu(cmd.bitmap);
priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
}

@@ -913,7 +917,7 @@

ret = lbs_get_channel(priv);
if (ret > 0) {
- priv->curbssparams.channel = ret;
+ priv->channel = ret;
ret = 0;
}
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -932,7 +936,7 @@
{
struct cmd_ds_802_11_rf_channel cmd;
#ifdef DEBUG
- u8 old_channel = priv->curbssparams.channel;
+ u8 old_channel = priv->channel;
#endif
int ret = 0;

@@ -947,36 +951,15 @@
if (ret)
goto out;

- priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel);
+ priv->channel = (uint8_t) le16_to_cpu(cmd.channel);
lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
- priv->curbssparams.channel);
+ priv->channel);

out:
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}

-static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
- struct cmd_ds_command *cmd)
-{
-
- lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_RSSI);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
- cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
-
- /* reset Beacon SNR/NF/RSSI values */
- priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
- priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
- priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
- priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
- priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
- priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
u8 cmd_action, void *pdata_buf)
{
@@ -1523,10 +1506,6 @@
cmd_action, pdata_buf);
break;

- case CMD_802_11_RSSI:
- ret = lbs_cmd_802_11_rssi(priv, cmdptr);
- break;
-
case CMD_802_11_SET_AFC:
case CMD_802_11_GET_AFC:

@@ -1540,10 +1519,12 @@
ret = 0;
goto done;

+#ifdef TODO
case CMD_802_11D_DOMAIN_INFO:
ret = lbs_cmd_802_11d_domain_info(priv, cmdptr,
cmd_no, cmd_action);
break;
+#endif

case CMD_802_11_TPC_CFG:
cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
@@ -1893,6 +1874,7 @@
(priv->psstate == PS_STATE_FULL_POWER) &&
((priv->connect_status == LBS_CONNECTED) ||
(priv->mesh_connect_status == LBS_CONNECTED))) {
+#ifdef TODO
if (priv->secinfo.WPAenabled ||
priv->secinfo.WPA2enabled) {
/* check for valid WPA group keys */
@@ -1909,6 +1891,7 @@
"go back to PS_SLEEP");
lbs_ps_sleep(priv, 0);
}
+#endif
}
}

@@ -1918,6 +1901,7 @@
return ret;
}

+#ifdef TODO
void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
{
union iwreq_data iwrq;
@@ -1941,6 +1925,7 @@

lbs_deb_leave(LBS_DEB_WEXT);
}
+#endif

static void lbs_send_confirmsleep(struct lbs_private *priv)
{
--- linux-wl.orig/drivers/net/wireless/libertas/cmdresp.c
+++ linux-wl/drivers/net/wireless/libertas/cmdresp.c
@@ -7,14 +7,14 @@
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <asm/unaligned.h>
-#include <net/iw_handler.h>
+#ifdef TODO
+//#include <net/iw_handler.h>
+#endif

#include "host.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
-#include "assoc.h"
-#include "wext.h"

/**
* @brief This function handles disconnect event. it
@@ -26,13 +26,16 @@
*/
void lbs_mac_event_disconnected(struct lbs_private *priv)
{
+#ifdef TODO
union iwreq_data wrqu;
+#endif

if (priv->connect_status != LBS_CONNECTED)
return;

lbs_deb_enter(LBS_DEB_ASSOC);

+#ifdef TODO
memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;

@@ -43,6 +46,7 @@

msleep_interruptible(1000);
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+#endif

/* report disconnect to upper layer */
netif_stop_queue(priv->dev);
@@ -53,14 +57,7 @@
priv->currenttxskb = NULL;
priv->tx_pending_len = 0;

- /* reset SNR/NF/RSSI values */
- memset(priv->SNR, 0x00, sizeof(priv->SNR));
- memset(priv->NF, 0x00, sizeof(priv->NF));
- memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
- memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
- memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
- priv->nextSNRNF = 0;
- priv->numSNRNF = 0;
+#ifdef TODO
priv->connect_status = LBS_DISCONNECTED;

/* Clear out associated SSID and BSSID since connection is
@@ -69,6 +66,7 @@
memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
priv->curbssparams.ssid_len = 0;
+#endif

if (priv->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
@@ -100,7 +98,9 @@
strcat(buf, "multicast ");
}

+#ifdef TODO
lbs_send_iwevcustom_event(priv, buf);
+#endif
lbs_deb_leave(LBS_DEB_CMD);
}

@@ -147,36 +147,6 @@
return ret;
}

-static int lbs_ret_802_11_rssi(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- /* store the non average value */
- priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
- priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor);
-
- priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
- priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor);
-
- priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
- CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
- priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-
- priv->RSSI[TYPE_BEACON][TYPE_AVG] =
- CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
-
- lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
- priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
- priv->RSSI[TYPE_BEACON][TYPE_AVG]);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
struct cmd_ds_command *resp)
{
@@ -223,13 +193,11 @@
case CMD_RET(CMD_802_11_BEACON_STOP):
break;

- case CMD_RET(CMD_802_11_RSSI):
- ret = lbs_ret_802_11_rssi(priv, resp);
- break;
-
+#ifdef TODO
case CMD_RET(CMD_802_11D_DOMAIN_INFO):
ret = lbs_ret_802_11d_domain_info(resp);
break;
+#endif

case CMD_RET(CMD_802_11_TPC_CFG):
spin_lock_irqsave(&priv->driver_lock, flags);
--- linux-wl.orig/drivers/net/wireless/libertas/ethtool.c
+++ linux-wl/drivers/net/wireless/libertas/ethtool.c
@@ -6,7 +6,6 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
-#include "wext.h"
#include "cmd.h"

static const char * mesh_stat_strings[]= {
--- linux-wl.orig/drivers/net/wireless/libertas/rx.c
+++ linux-wl/drivers/net/wireless/libertas/rx.c
@@ -8,7 +8,6 @@
#include "radiotap.h"
#include "decl.h"
#include "dev.h"
-#include "wext.h"

struct eth803hdr {
u8 dest_addr[6];
@@ -38,99 +37,6 @@
struct sk_buff *skb);

/**
- * @brief This function computes the avgSNR .
- *
- * @param priv A pointer to struct lbs_private structure
- * @return avgSNR
- */
-static u8 lbs_getavgsnr(struct lbs_private *priv)
-{
- u8 i;
- u16 temp = 0;
- if (priv->numSNRNF == 0)
- return 0;
- for (i = 0; i < priv->numSNRNF; i++)
- temp += priv->rawSNR[i];
- return (u8) (temp / priv->numSNRNF);
-
-}
-
-/**
- * @brief This function computes the AvgNF
- *
- * @param priv A pointer to struct lbs_private structure
- * @return AvgNF
- */
-static u8 lbs_getavgnf(struct lbs_private *priv)
-{
- u8 i;
- u16 temp = 0;
- if (priv->numSNRNF == 0)
- return 0;
- for (i = 0; i < priv->numSNRNF; i++)
- temp += priv->rawNF[i];
- return (u8) (temp / priv->numSNRNF);
-
-}
-
-/**
- * @brief This function save the raw SNR/NF to our internel buffer
- *
- * @param priv A pointer to struct lbs_private structure
- * @param prxpd A pointer to rxpd structure of received packet
- * @return n/a
- */
-static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
-{
- if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
- priv->numSNRNF++;
- priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
- priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
- priv->nextSNRNF++;
- if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
- priv->nextSNRNF = 0;
- return;
-}
-
-/**
- * @brief This function computes the RSSI in received packet.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param prxpd A pointer to rxpd structure of received packet
- * @return n/a
- */
-static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
-{
-
- lbs_deb_enter(LBS_DEB_RX);
-
- lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
- lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
- priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
- priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
- priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
- lbs_save_rawSNRNF(priv, p_rx_pd);
-
- priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
- priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
- lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
- priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
- priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
- CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
- priv->NF[TYPE_RXPD][TYPE_NOAVG]);
-
- priv->RSSI[TYPE_RXPD][TYPE_AVG] =
- CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
- lbs_deb_leave(LBS_DEB_RX);
-}
-
-/**
* @brief This function processes received packet and forwards it
* to kernel/upper layer
*
@@ -238,8 +144,6 @@
if (priv->enablehwauto)
priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);

- lbs_compute_rssi(priv, p_rx_pd);
-
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
@@ -366,8 +270,6 @@
if (priv->enablehwauto)
priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);

- lbs_compute_rssi(priv, prxpd);
-
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
--- linux-wl.orig/drivers/net/wireless/libertas/tx.c
+++ linux-wl/drivers/net/wireless/libertas/tx.c
@@ -10,7 +10,6 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
-#include "wext.h"

/**
* @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
--- linux-wl.orig/drivers/net/wireless/libertas/wext.h
+++ linux-wl/drivers/net/wireless/libertas/wext.h
@@ -1,3 +1,6 @@
+#error don't include wext.h
+/* TODO: remove this file */
+
/**
* This file contains definition for IOCTL call.
*/
--- linux-wl.orig/drivers/net/wireless/libertas/11d.h
+++ linux-wl/drivers/net/wireless/libertas/11d.h
@@ -1,3 +1,6 @@
+#error don't include 11d.h
+/* TODO: remove this file */
+
/**
* This header file contains data structures and
* function declarations of 802.11d
--- linux-wl.orig/drivers/net/wireless/libertas/cmd.h
+++ linux-wl/drivers/net/wireless/libertas/cmd.h
@@ -72,12 +72,14 @@
uint16_t cmd_action, uint16_t *timeout);
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
struct sleep_params *sp);
+#ifdef TODO
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc);
int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
uint16_t *enable);
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc);
+#endif

int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
s16 *maxlevel);
--- linux-wl.orig/drivers/net/wireless/libertas/debugfs.c
+++ linux-wl/drivers/net/wireless/libertas/debugfs.c
@@ -4,7 +4,9 @@
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/string.h>
-#include <net/iw_handler.h>
+#ifdef TODO
+//#include <net/iw_handler.h>
+#endif
#include <net/lib80211.h>

#include "dev.h"
@@ -14,10 +16,12 @@
#include "cmd.h"

static struct dentry *lbs_dir;
+#ifdef TODO
static char *szStates[] = {
"Connected",
"Disconnected"
};
+#endif

#ifdef PROC_DEBUG
static void lbs_debug_init(struct lbs_private *priv);
@@ -48,8 +52,10 @@
if (!buf)
return -ENOMEM;

+#ifdef TODO
pos += snprintf(buf+pos, len-pos, "state = %s\n",
szStates[priv->connect_status]);
+#endif
pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
(u32) priv->regioncode);

@@ -60,6 +66,7 @@
}


+#ifdef TODO
static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -103,6 +110,7 @@
free_page(addr);
return res;
}
+#endif

static ssize_t lbs_sleepparams_write(struct file *file,
const char __user *user_buf, size_t count,
@@ -722,8 +730,10 @@

static const struct lbs_debugfs_files debugfs_files[] = {
{ "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
+#ifdef TODO
{ "getscantable", 0444, FOPS(lbs_getscantable,
write_file_dummy), },
+#endif
{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
lbs_sleepparams_write), },
};
--- linux-wl.orig/drivers/net/wireless/libertas/hostcmd.h
+++ linux-wl/drivers/net/wireless/libertas/hostcmd.h
@@ -6,8 +6,10 @@
#define _LBS_HOSTCMD_H

#include <linux/wireless.h>
-#include "11d.h"
#include "types.h"
+#include "defs.h"
+
+struct lbs_private;

/* 802.11-related definitions */

@@ -433,19 +435,12 @@
} __attribute__ ((packed));

struct cmd_ds_802_11_rssi {
- /* weighting factor */
- __le16 N;
-
- __le16 reserved_0;
- __le16 reserved_1;
- __le16 reserved_2;
-} __attribute__ ((packed));
+ struct cmd_header hdr;

-struct cmd_ds_802_11_rssi_rsp {
- __le16 SNR;
- __le16 noisefloor;
- __le16 avgSNR;
- __le16 avgnoisefloor;
+ __le16 n_or_snr;
+ __le16 nf;
+ __le16 avg_snr;
+ __le16 avg_nf;
} __attribute__ ((packed));

struct cmd_ds_802_11_mac_address {
@@ -706,7 +701,9 @@
} __attribute__ ((packed));

struct cmd_tx_rate_query {
- __le16 txrate;
+ struct cmd_header hdr;
+
+ __le16 tx_rate;
} __attribute__ ((packed));

struct cmd_ds_get_tsf {
@@ -772,28 +769,27 @@
/* command Body */
union {
struct cmd_ds_802_11_ps_mode psmode;
- struct cmd_ds_802_11_get_stat gstat;
- struct cmd_ds_802_3_get_stat gstat_8023;
- struct cmd_ds_802_11_rf_antenna rant;
struct cmd_ds_802_11_monitor_mode monitor;
- struct cmd_ds_802_11_rssi rssi;
- struct cmd_ds_802_11_rssi_rsp rssirsp;
struct cmd_ds_mac_reg_access macreg;
struct cmd_ds_bbp_reg_access bbpreg;
struct cmd_ds_rf_reg_access rfreg;
-
- struct cmd_ds_802_11d_domain_info domaininfo;
- struct cmd_ds_802_11d_domain_info domaininforesp;
-
struct cmd_ds_802_11_tpc_cfg tpccfg;
struct cmd_ds_802_11_afc afc;
struct cmd_ds_802_11_led_ctrl ledgpio;
-
- struct cmd_tx_rate_query txrate;
struct cmd_ds_bt_access bt;
struct cmd_ds_fwt_access fwt;
struct cmd_ds_get_tsf gettsf;
struct cmd_ds_802_11_beacon_control bcn_ctrl;
+#ifdef TODO
+ struct cmd_ds_802_11_get_stat gstat;
+ struct cmd_ds_802_3_get_stat gstat_8023;
+ struct cmd_ds_802_11_rf_antenna rant;
+ struct cmd_ds_802_11_rssi rssi;
+ struct cmd_ds_802_11_rssi_rsp rssirsp;
+ struct cmd_ds_802_11d_domain_info domaininfo;
+ struct cmd_ds_802_11d_domain_info domaininforesp;
+ struct cmd_tx_rate_query txrate;
+#endif
} params;
} __attribute__ ((packed));

--- linux-wl.orig/drivers/net/wireless/libertas/decl.h
+++ linux-wl/drivers/net/wireless/libertas/decl.h
@@ -46,7 +46,9 @@
int result);
netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev);
+#ifdef TODO
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
+#endif

int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);


--
http://www.holgerschurig.de


2009-10-14 15:14:49

by Holger Schurig

[permalink] [raw]
Subject: Re: [WIP, RFC] libertas: allow scanning via "iw"

Oops, didn't change the subject. Of course it can now do more
than just scanning ...

2009-10-16 12:16:58

by Holger Schurig

[permalink] [raw]
Subject: Re: [WIP, RFC] libertas: allow scanning via "iw"

> It'd be easier to read and see what the patch does if you
> actually removed all the stuff that is no longer necessary :)

Sure, you can easily get a patch that removes all the cruft that
don't need so far.

As I managed to get a connection via WEP, WEP104, WPA, WPA2
NO-ENCRYPTION to an AP today (including pings via the link),
I'll send a new WIP/RFC anyway.

--
http://www.holgerschurig.de

2009-10-16 11:38:37

by Johannes Berg

[permalink] [raw]
Subject: Re: [WIP, RFC] libertas: allow scanning via "iw"

On Wed, 2009-10-14 at 16:52 +0200, Holger Schurig wrote:
> Do not apply, but please look at the code and comment harshly :-)

>
> +#ifdef TODO
> /* Scan results list */
> struct list_head network_list;
> struct list_head network_free_list;
> struct bss_descriptor *networks;
> +#endif

It'd be easier to read and see what the patch does if you actually
removed all the stuff that is no longer necessary :)

johannes


Attachments:
signature.asc (801.00 B)
This is a digitally signed message part