diff options
author | Pavel Roskin <proski@gnu.org> | 2005-09-09 18:43:02 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:30:54 -0400 |
commit | 343c686c04eec556645f251f7d6c9b3d7335dae0 (patch) | |
tree | 2713fbd5e71f7a7dbe94634a1bc4eb81a1ed8af5 | |
parent | b81e8e1f4a51556586f72711a165bc3a0de230f3 (diff) |
[PATCH] orinoco: WE-18 support
Author: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: Pavel Roskin <proski@gnu.org>
Use new Wireless Extension API for wireless stats.
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/net/wireless/orinoco.c | 137 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco.h | 6 |
2 files changed, 33 insertions, 110 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 8de49fe57233..639b8e4ba684 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -137,7 +137,7 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); | |||
137 | 137 | ||
138 | /* We do this this way to avoid ifdefs in the actual code */ | 138 | /* We do this this way to avoid ifdefs in the actual code */ |
139 | #ifdef WIRELESS_SPY | 139 | #ifdef WIRELESS_SPY |
140 | #define SPY_NUMBER(priv) (priv->spy_number) | 140 | #define SPY_NUMBER(priv) (priv->spy_data.spy_number) |
141 | #else | 141 | #else |
142 | #define SPY_NUMBER(priv) 0 | 142 | #define SPY_NUMBER(priv) 0 |
143 | #endif /* WIRELESS_SPY */ | 143 | #endif /* WIRELESS_SPY */ |
@@ -396,10 +396,10 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) | |||
396 | /* If a spy address is defined, we report stats of the | 396 | /* If a spy address is defined, we report stats of the |
397 | * first spy address - Jean II */ | 397 | * first spy address - Jean II */ |
398 | if (SPY_NUMBER(priv)) { | 398 | if (SPY_NUMBER(priv)) { |
399 | wstats->qual.qual = priv->spy_stat[0].qual; | 399 | wstats->qual.qual = priv->spy_data.spy_stat[0].qual; |
400 | wstats->qual.level = priv->spy_stat[0].level; | 400 | wstats->qual.level = priv->spy_data.spy_stat[0].level; |
401 | wstats->qual.noise = priv->spy_stat[0].noise; | 401 | wstats->qual.noise = priv->spy_data.spy_stat[0].noise; |
402 | wstats->qual.updated = priv->spy_stat[0].updated; | 402 | wstats->qual.updated = priv->spy_data.spy_stat[0].updated; |
403 | } | 403 | } |
404 | } else { | 404 | } else { |
405 | struct { | 405 | struct { |
@@ -718,18 +718,13 @@ static inline int is_ethersnap(void *_hdr) | |||
718 | static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, | 718 | static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, |
719 | int level, int noise) | 719 | int level, int noise) |
720 | { | 720 | { |
721 | struct orinoco_private *priv = netdev_priv(dev); | 721 | struct iw_quality wstats; |
722 | int i; | 722 | wstats.level = level - 0x95; |
723 | 723 | wstats.noise = noise - 0x95; | |
724 | /* Gather wireless spy statistics: for each packet, compare the | 724 | wstats.qual = (level > noise) ? (level - noise) : 0; |
725 | * source address with out list, and if match, get the stats... */ | 725 | wstats.updated = 7; |
726 | for (i = 0; i < priv->spy_number; i++) | 726 | /* Update spy records */ |
727 | if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) { | 727 | wireless_spy_update(dev, mac, &wstats); |
728 | priv->spy_stat[i].level = level - 0x95; | ||
729 | priv->spy_stat[i].noise = noise - 0x95; | ||
730 | priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0; | ||
731 | priv->spy_stat[i].updated = 7; | ||
732 | } | ||
733 | } | 728 | } |
734 | 729 | ||
735 | static void orinoco_stat_gather(struct net_device *dev, | 730 | static void orinoco_stat_gather(struct net_device *dev, |
@@ -2458,8 +2453,11 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
2458 | dev->watchdog_timeo = HZ; /* 1 second timeout */ | 2453 | dev->watchdog_timeo = HZ; /* 1 second timeout */ |
2459 | dev->get_stats = orinoco_get_stats; | 2454 | dev->get_stats = orinoco_get_stats; |
2460 | dev->ethtool_ops = &orinoco_ethtool_ops; | 2455 | dev->ethtool_ops = &orinoco_ethtool_ops; |
2461 | dev->get_wireless_stats = orinoco_get_wireless_stats; | ||
2462 | dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; | 2456 | dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; |
2457 | #ifdef WIRELESS_SPY | ||
2458 | priv->wireless_data.spy_data = &priv->spy_data; | ||
2459 | dev->wireless_data = &priv->wireless_data; | ||
2460 | #endif | ||
2463 | dev->change_mtu = orinoco_change_mtu; | 2461 | dev->change_mtu = orinoco_change_mtu; |
2464 | dev->set_multicast_list = orinoco_set_multicast_list; | 2462 | dev->set_multicast_list = orinoco_set_multicast_list; |
2465 | /* we use the default eth_mac_addr for setting the MAC addr */ | 2463 | /* 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, | |||
2831 | } | 2829 | } |
2832 | } | 2830 | } |
2833 | 2831 | ||
2834 | if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | 2832 | if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){ |
2835 | /* Quality stats meaningless in ad-hoc mode */ | 2833 | /* Quality stats meaningless in ad-hoc mode */ |
2836 | } else { | 2834 | } else { |
2837 | range->max_qual.qual = 0x8b - 0x2f; | 2835 | range->max_qual.qual = 0x8b - 0x2f; |
@@ -2878,6 +2876,14 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, | |||
2878 | range->min_r_time = 0; | 2876 | range->min_r_time = 0; |
2879 | range->max_r_time = 65535 * 1000; /* ??? */ | 2877 | range->max_r_time = 65535 * 1000; /* ??? */ |
2880 | 2878 | ||
2879 | /* Event capability (kernel) */ | ||
2880 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); | ||
2881 | /* Event capability (driver) */ | ||
2882 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); | ||
2883 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); | ||
2884 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); | ||
2885 | IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); | ||
2886 | |||
2881 | TRACE_EXIT(dev->name); | 2887 | TRACE_EXIT(dev->name); |
2882 | 2888 | ||
2883 | return 0; | 2889 | return 0; |
@@ -3837,92 +3843,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev, | |||
3837 | return err; | 3843 | return err; |
3838 | } | 3844 | } |
3839 | 3845 | ||
3840 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode | ||
3841 | * Jean II */ | ||
3842 | static int orinoco_ioctl_setspy(struct net_device *dev, | ||
3843 | struct iw_request_info *info, | ||
3844 | struct iw_point *srq, | ||
3845 | char *extra) | ||
3846 | |||
3847 | { | ||
3848 | struct orinoco_private *priv = netdev_priv(dev); | ||
3849 | struct sockaddr *address = (struct sockaddr *) extra; | ||
3850 | int number = srq->length; | ||
3851 | int i; | ||
3852 | unsigned long flags; | ||
3853 | |||
3854 | /* Make sure nobody mess with the structure while we do */ | ||
3855 | if (orinoco_lock(priv, &flags) != 0) | ||
3856 | return -EBUSY; | ||
3857 | |||
3858 | /* orinoco_lock() doesn't disable interrupts, so make sure the | ||
3859 | * interrupt rx path don't get confused while we copy */ | ||
3860 | priv->spy_number = 0; | ||
3861 | |||
3862 | if (number > 0) { | ||
3863 | /* Extract the addresses */ | ||
3864 | for (i = 0; i < number; i++) | ||
3865 | memcpy(priv->spy_address[i], address[i].sa_data, | ||
3866 | ETH_ALEN); | ||
3867 | /* Reset stats */ | ||
3868 | memset(priv->spy_stat, 0, | ||
3869 | sizeof(struct iw_quality) * IW_MAX_SPY); | ||
3870 | /* Set number of addresses */ | ||
3871 | priv->spy_number = number; | ||
3872 | } | ||
3873 | |||
3874 | /* Now, let the others play */ | ||
3875 | orinoco_unlock(priv, &flags); | ||
3876 | |||
3877 | /* Do NOT call commit handler */ | ||
3878 | return 0; | ||
3879 | } | ||
3880 | |||
3881 | static int orinoco_ioctl_getspy(struct net_device *dev, | ||
3882 | struct iw_request_info *info, | ||
3883 | struct iw_point *srq, | ||
3884 | char *extra) | ||
3885 | { | ||
3886 | struct orinoco_private *priv = netdev_priv(dev); | ||
3887 | struct sockaddr *address = (struct sockaddr *) extra; | ||
3888 | int number; | ||
3889 | int i; | ||
3890 | unsigned long flags; | ||
3891 | |||
3892 | if (orinoco_lock(priv, &flags) != 0) | ||
3893 | return -EBUSY; | ||
3894 | |||
3895 | number = priv->spy_number; | ||
3896 | /* Create address struct */ | ||
3897 | for (i = 0; i < number; i++) { | ||
3898 | memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN); | ||
3899 | address[i].sa_family = AF_UNIX; | ||
3900 | } | ||
3901 | if (number > 0) { | ||
3902 | /* Create address struct */ | ||
3903 | for (i = 0; i < number; i++) { | ||
3904 | memcpy(address[i].sa_data, priv->spy_address[i], | ||
3905 | ETH_ALEN); | ||
3906 | address[i].sa_family = AF_UNIX; | ||
3907 | } | ||
3908 | /* Copy stats */ | ||
3909 | /* In theory, we should disable irqs while copying the stats | ||
3910 | * because the rx path might update it in the middle... | ||
3911 | * Bah, who care ? - Jean II */ | ||
3912 | memcpy(extra + (sizeof(struct sockaddr) * number), | ||
3913 | priv->spy_stat, sizeof(struct iw_quality) * number); | ||
3914 | } | ||
3915 | /* Reset updated flags. */ | ||
3916 | for (i = 0; i < number; i++) | ||
3917 | priv->spy_stat[i].updated = 0; | ||
3918 | |||
3919 | orinoco_unlock(priv, &flags); | ||
3920 | |||
3921 | srq->length = number; | ||
3922 | |||
3923 | return 0; | ||
3924 | } | ||
3925 | |||
3926 | /* Trigger a scan (look for other cells in the vicinity */ | 3846 | /* Trigger a scan (look for other cells in the vicinity */ |
3927 | static int orinoco_ioctl_setscan(struct net_device *dev, | 3847 | static int orinoco_ioctl_setscan(struct net_device *dev, |
3928 | struct iw_request_info *info, | 3848 | struct iw_request_info *info, |
@@ -4353,8 +4273,10 @@ static const iw_handler orinoco_handler[] = { | |||
4353 | [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens, | 4273 | [SIOCSIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens, |
4354 | [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens, | 4274 | [SIOCGIWSENS -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens, |
4355 | [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange, | 4275 | [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange, |
4356 | [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy, | 4276 | [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, |
4357 | [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy, | 4277 | [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, |
4278 | [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, | ||
4279 | [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, | ||
4358 | [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap, | 4280 | [SIOCSIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap, |
4359 | [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap, | 4281 | [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap, |
4360 | [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan, | 4282 | [SIOCSIWSCAN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan, |
@@ -4399,6 +4321,7 @@ static const struct iw_handler_def orinoco_handler_def = { | |||
4399 | .standard = orinoco_handler, | 4321 | .standard = orinoco_handler, |
4400 | .private = orinoco_private_handler, | 4322 | .private = orinoco_private_handler, |
4401 | .private_args = orinoco_privtab, | 4323 | .private_args = orinoco_privtab, |
4324 | .get_wireless_stats = orinoco_get_wireless_stats, | ||
4402 | }; | 4325 | }; |
4403 | 4326 | ||
4404 | static void orinoco_get_drvinfo(struct net_device *dev, | 4327 | static void orinoco_get_drvinfo(struct net_device *dev, |
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index 2f213a7103fe..c800563034a7 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <linux/wireless.h> | 15 | #include <linux/wireless.h> |
16 | #include <net/iw_handler.h> | ||
16 | #include <linux/version.h> | 17 | #include <linux/version.h> |
17 | 18 | ||
18 | #include "hermes.h" | 19 | #include "hermes.h" |
@@ -112,9 +113,8 @@ struct orinoco_private { | |||
112 | u16 pm_on, pm_mcast, pm_period, pm_timeout; | 113 | u16 pm_on, pm_mcast, pm_period, pm_timeout; |
113 | u16 preamble; | 114 | u16 preamble; |
114 | #ifdef WIRELESS_SPY | 115 | #ifdef WIRELESS_SPY |
115 | int spy_number; | 116 | struct iw_spy_data spy_data; /* iwspy support */ |
116 | u_char spy_address[IW_MAX_SPY][ETH_ALEN]; | 117 | struct iw_public_data wireless_data; |
117 | struct iw_quality spy_stat[IW_MAX_SPY]; | ||
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | /* Configuration dependent variables */ | 120 | /* Configuration dependent variables */ |