Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 343c686c authored by Pavel Roskin's avatar Pavel Roskin Committed by Jeff Garzik
Browse files

[PATCH] orinoco: WE-18 support



Author: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: default avatarPavel Roskin <proski@gnu.org>

Use new Wireless Extension API for wireless stats.
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent b81e8e1f
Loading
Loading
Loading
Loading
+30 −107
Original line number Diff line number Diff line
@@ -137,7 +137,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");

/* We do this this way to avoid ifdefs in the actual code */
#ifdef WIRELESS_SPY
#define SPY_NUMBER(priv)	(priv->spy_number)
#define SPY_NUMBER(priv)	(priv->spy_data.spy_number)
#else
#define SPY_NUMBER(priv)	0
#endif /* WIRELESS_SPY */
@@ -396,10 +396,10 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
		/* If a spy address is defined, we report stats of the
		 * first spy address - Jean II */
		if (SPY_NUMBER(priv)) {
			wstats->qual.qual = priv->spy_stat[0].qual;
			wstats->qual.level = priv->spy_stat[0].level;
			wstats->qual.noise = priv->spy_stat[0].noise;
			wstats->qual.updated = priv->spy_stat[0].updated;
			wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
			wstats->qual.level = priv->spy_data.spy_stat[0].level;
			wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
			wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
		}
	} else {
		struct {
@@ -718,18 +718,13 @@ static inline int is_ethersnap(void *_hdr)
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
				      int level, int noise)
{
	struct orinoco_private *priv = netdev_priv(dev);
	int i;

	/* Gather wireless spy statistics: for each packet, compare the
	 * source address with out list, and if match, get the stats... */
	for (i = 0; i < priv->spy_number; i++)
		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
			priv->spy_stat[i].level = level - 0x95;
			priv->spy_stat[i].noise = noise - 0x95;
			priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
			priv->spy_stat[i].updated = 7;
		}
	struct iw_quality wstats;
	wstats.level = level - 0x95;
	wstats.noise = noise - 0x95;
	wstats.qual = (level > noise) ? (level - noise) : 0;
	wstats.updated = 7;
	/* Update spy records */
	wireless_spy_update(dev, mac, &wstats);
}

static void orinoco_stat_gather(struct net_device *dev,
@@ -2458,8 +2453,11 @@ struct net_device *alloc_orinocodev(int sizeof_card,
	dev->watchdog_timeo = HZ; /* 1 second timeout */
	dev->get_stats = orinoco_get_stats;
	dev->ethtool_ops = &orinoco_ethtool_ops;
	dev->get_wireless_stats = orinoco_get_wireless_stats;
	dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
#ifdef WIRELESS_SPY
	priv->wireless_data.spy_data = &priv->spy_data;
	dev->wireless_data = &priv->wireless_data;
#endif
	dev->change_mtu = orinoco_change_mtu;
	dev->set_multicast_list = orinoco_set_multicast_list;
	/* we use the default eth_mac_addr for setting the MAC addr */
@@ -2831,7 +2829,7 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
		}
	}

	if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
	if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
		/* Quality stats meaningless in ad-hoc mode */
	} else {
		range->max_qual.qual = 0x8b - 0x2f;
@@ -2878,6 +2876,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
	range->min_r_time = 0;
	range->max_r_time = 65535 * 1000;	/* ??? */

	/* Event capability (kernel) */
	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
	/* Event capability (driver) */
	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
	IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);

	TRACE_EXIT(dev->name);

	return 0;
@@ -3837,92 +3843,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
	return err;
}

/* Spy is used for link quality/strength measurements in Ad-Hoc mode
 * Jean II */
static int orinoco_ioctl_setspy(struct net_device *dev,
				struct iw_request_info *info,
				struct iw_point *srq,
				char *extra)

{
	struct orinoco_private *priv = netdev_priv(dev);
	struct sockaddr *address = (struct sockaddr *) extra;
	int number = srq->length;
	int i;
	unsigned long flags;

	/* Make sure nobody mess with the structure while we do */
	if (orinoco_lock(priv, &flags) != 0)
		return -EBUSY;

	/* orinoco_lock() doesn't disable interrupts, so make sure the
	 * interrupt rx path don't get confused while we copy */
	priv->spy_number = 0;

	if (number > 0) {
		/* Extract the addresses */
		for (i = 0; i < number; i++)
			memcpy(priv->spy_address[i], address[i].sa_data,
			       ETH_ALEN);
		/* Reset stats */
		memset(priv->spy_stat, 0,
		       sizeof(struct iw_quality) * IW_MAX_SPY);
		/* Set number of addresses */
		priv->spy_number = number;
	}

	/* Now, let the others play */
	orinoco_unlock(priv, &flags);

	/* Do NOT call commit handler */
	return 0;
}

static int orinoco_ioctl_getspy(struct net_device *dev,
				struct iw_request_info *info,
				struct iw_point *srq,
				char *extra)
{
	struct orinoco_private *priv = netdev_priv(dev);
	struct sockaddr *address = (struct sockaddr *) extra;
	int number;
	int i;
	unsigned long flags;

	if (orinoco_lock(priv, &flags) != 0)
		return -EBUSY;

	number = priv->spy_number;
	/* Create address struct */
	for (i = 0; i < number; i++) {
		memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
		address[i].sa_family = AF_UNIX;
	}
	if (number > 0) {
		/* Create address struct */
		for (i = 0; i < number; i++) {
			memcpy(address[i].sa_data, priv->spy_address[i],
			       ETH_ALEN);
			address[i].sa_family = AF_UNIX;
		}
		/* Copy stats */
		/* In theory, we should disable irqs while copying the stats
		 * because the rx path might update it in the middle...
		 * Bah, who care ? - Jean II */
		memcpy(extra  + (sizeof(struct sockaddr) * number),
		       priv->spy_stat, sizeof(struct iw_quality) * number);
	}
	/* Reset updated flags. */
	for (i = 0; i < number; i++)
		priv->spy_stat[i].updated = 0;

	orinoco_unlock(priv, &flags);

	srq->length = number;

	return 0;
}

/* Trigger a scan (look for other cells in the vicinity */
static int orinoco_ioctl_setscan(struct net_device *dev,
				 struct iw_request_info *info,
@@ -4353,8 +4273,10 @@ static const iw_handler orinoco_handler[] = {
	[SIOCSIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
	[SIOCGIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
	[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
	[SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy,
	[SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy,
	[SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
	[SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
	[SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
	[SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
	[SIOCSIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
	[SIOCGIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
	[SIOCSIWSCAN  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
@@ -4399,6 +4321,7 @@ static const struct iw_handler_def orinoco_handler_def = {
	.standard = orinoco_handler,
	.private = orinoco_private_handler,
	.private_args = orinoco_privtab,
	.get_wireless_stats = orinoco_get_wireless_stats,
};

static void orinoco_get_drvinfo(struct net_device *dev,
+3 −3
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <linux/version.h>

#include "hermes.h"
@@ -112,9 +113,8 @@ struct orinoco_private {
	u16 pm_on, pm_mcast, pm_period, pm_timeout;
	u16 preamble;
#ifdef WIRELESS_SPY
	int			spy_number;
	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
	struct iw_quality	spy_stat[IW_MAX_SPY];
 	struct iw_spy_data spy_data; /* iwspy support */
	struct iw_public_data	wireless_data;
#endif

	/* Configuration dependent variables */