wext.c revision cb1576a829826d56fab59e22aa3af8c5a7db9936
1cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* Wireless extensions support. 2cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * 3cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * See copyright notice in main.c 4cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy */ 5cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include <linux/kernel.h> 6cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include <linux/if_arp.h> 7cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include <linux/wireless.h> 8cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include <linux/ieee80211.h> 9cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include <net/iw_handler.h> 10cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 11cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "hermes.h" 12cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "hermes_rid.h" 13cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "orinoco.h" 14cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 15cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "hw.h" 16cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "mic.h" 17cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "scan.h" 18cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "main.h" 19cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 20cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#include "wext.h" 21cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 22cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#define MAX_RID_LEN 1024 23cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 24cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) 25cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 26cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 27cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 28cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_statistics *wstats = &priv->wstats; 29cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err; 30cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 31cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 32cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!netif_device_present(dev)) { 33cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n", 34cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy dev->name); 35cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return NULL; /* FIXME: Can we do better than this? */ 36cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 37cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 38cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* If busy, return the old stats. Returning NULL may cause 39cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * the interface to disappear from /proc/net/wireless */ 40cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 41cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return wstats; 42cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 43cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* We can't really wait for the tallies inquiry command to 44cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * complete, so we just use the previous results and trigger 45cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * a new tallies inquiry command for next time - Jean II */ 46cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* FIXME: Really we should wait for the inquiry to come back - 47cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * as it is the stats we give don't make a whole lot of sense. 48cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Unfortunately, it's not clear how to do that within the 49cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * wireless extensions framework: I think we're in user 50cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * context, but a lock seems to be held by the time we get in 51cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * here so we're not safe to sleep here. */ 52cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_inquire(hw, HERMES_INQ_TALLIES); 53cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 54cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->iw_mode == IW_MODE_ADHOC) { 55cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(&wstats->qual, 0, sizeof(wstats->qual)); 56cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* If a spy address is defined, we report stats of the 57cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * first spy address - Jean II */ 58cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (SPY_NUMBER(priv)) { 59cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.qual = priv->spy_data.spy_stat[0].qual; 60cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.level = priv->spy_data.spy_stat[0].level; 61cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.noise = priv->spy_data.spy_stat[0].noise; 62cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.updated = 63cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->spy_data.spy_stat[0].updated; 64cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 65cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 66cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct { 67cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy __le16 qual, signal, noise, unused; 68cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } __attribute__ ((packed)) cq; 69cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 70cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = HERMES_READ_RECORD(hw, USER_BAP, 71cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_COMMSQUALITY, &cq); 72cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 73cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!err) { 74cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.qual = (int)le16_to_cpu(cq.qual); 75cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; 76cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; 77cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wstats->qual.updated = 78cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 79cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 80cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 81cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 82cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 83cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return wstats; 84cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 85cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 86cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/********************************************************************/ 87cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* Wireless extensions */ 88cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/********************************************************************/ 89cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 90cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getname(struct net_device *dev, 91cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 92cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *name, 93cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 94cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 95cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 96cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int numrates; 97cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err; 98cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 99cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0); 100cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 101cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!err && (numrates > 2)) 102cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy strcpy(name, "IEEE 802.11b"); 103cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 104cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy strcpy(name, "IEEE 802.11-DS"); 105cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 106cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 107cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 108cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 109cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setwap(struct net_device *dev, 110cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 111cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct sockaddr *ap_addr, 112cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 113cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 114cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 115cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = -EINPROGRESS; /* Call commit handler */ 116cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 117cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 118cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 119cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 120cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 121cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 122cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 123cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Enable automatic roaming - no sanity checks are needed */ 124cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || 125cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { 126cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->bssid_fixed = 0; 127cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(priv->desired_bssid, 0, ETH_ALEN); 128cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 129cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* "off" means keep existing connection */ 130cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ap_addr->sa_data[0] == 0) { 131cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy __orinoco_hw_set_wap(priv); 132cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = 0; 133cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 134cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 135cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 136cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 137cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->firmware_type == FIRMWARE_TYPE_AGERE) { 138cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't " 139cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "support manual roaming\n", 140cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy dev->name); 141cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EOPNOTSUPP; 142cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 143cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 144cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 145cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->iw_mode != IW_MODE_INFRA) { 146cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Manual roaming supported only in " 147cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "managed mode\n", dev->name); 148cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EOPNOTSUPP; 149cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 150cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 151cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 152cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Intersil firmware hangs without Desired ESSID */ 153cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL && 154cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy strlen(priv->desired_essid) == 0) { 155cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Desired ESSID must be set for " 156cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "manual roaming\n", dev->name); 157cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EOPNOTSUPP; 158cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 159cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 160cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 161cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Finally, enable manual roaming */ 162cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->bssid_fixed = 1; 163cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN); 164cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 165cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 166cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 167cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 168cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 169cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 170cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getwap(struct net_device *dev, 171cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 172cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct sockaddr *ap_addr, 173cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 174cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 175cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 176cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 177cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 178cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 179cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 180cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 181cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 182cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 183cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 184cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ap_addr->sa_family = ARPHRD_ETHER; 185cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, 186cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ETH_ALEN, NULL, ap_addr->sa_data); 187cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 188cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 189cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 190cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 191cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 192cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 193cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setmode(struct net_device *dev, 194cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 195cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u32 *mode, 196cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 197cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 198cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 199cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = -EINPROGRESS; /* Call commit handler */ 200cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 201cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 202cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->iw_mode == *mode) 203cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 204cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 205cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 206cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 207cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 208cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (*mode) { 209cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_MODE_ADHOC: 210cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_ibss && !priv->has_port3) 211cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EOPNOTSUPP; 212cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 213cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 214cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_MODE_INFRA: 215cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 216cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 217cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_MODE_MONITOR: 218cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->broken_monitor && !force_monitor) { 219cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Monitor mode support is " 220cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "buggy in this firmware, not enabling\n", 221cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy dev->name); 222cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EOPNOTSUPP; 223cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 224cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 225cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 226cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy default: 227cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EOPNOTSUPP; 228cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 229cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 230cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 231cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err == -EINPROGRESS) { 232cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->iw_mode = *mode; 233cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy set_port_type(priv); 234cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 235cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 236cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 237cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 238cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 239cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 240cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 241cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getmode(struct net_device *dev, 242cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 243cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u32 *mode, 244cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 245cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 246cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 247cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 248cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy *mode = priv->iw_mode; 249cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 250cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 251cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 252cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getiwrange(struct net_device *dev, 253cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 254cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *rrq, 255cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 256cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 257cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 258cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 259cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_range *range = (struct iw_range *) extra; 260cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int numrates; 261cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int i, k; 262cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 263cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->length = sizeof(struct iw_range); 264cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(range, 0, sizeof(struct iw_range)); 265cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 266cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->we_version_compiled = WIRELESS_EXT; 267cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->we_version_source = 22; 268cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 269cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Set available channels/frequencies */ 270cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->num_channels = NUM_CHANNELS; 271cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy k = 0; 272cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy for (i = 0; i < NUM_CHANNELS; i++) { 273cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->channel_mask & (1 << i)) { 274cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->freq[k].i = i + 1; 275cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->freq[k].m = (ieee80211_dsss_chan_to_freq(i + 1) * 276cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 100000); 277cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->freq[k].e = 1; 278cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy k++; 279cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 280cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 281cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (k >= IW_MAX_FREQUENCIES) 282cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 283cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 284cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->num_frequency = k; 285cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->sensitivity = 3; 286cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 287cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_wep) { 288cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_encoding_tokens = ORINOCO_MAX_KEYS; 289cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->encoding_size[0] = SMALL_KEY_SIZE; 290cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->num_encoding_sizes = 1; 291cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 292cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_big_wep) { 293cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->encoding_size[1] = LARGE_KEY_SIZE; 294cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->num_encoding_sizes = 2; 295cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 296cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 297cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 298cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_wpa) 299cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP; 300cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 301cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))) { 302cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Quality stats meaningless in ad-hoc mode */ 303cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 304cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_qual.qual = 0x8b - 0x2f; 305cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_qual.level = 0x2f - 0x95 - 1; 306cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_qual.noise = 0x2f - 0x95 - 1; 307cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Need to get better values */ 308cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->avg_qual.qual = 0x24; 309cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->avg_qual.level = 0xC2; 310cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->avg_qual.noise = 0x9E; 311cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 312cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 313cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = orinoco_hw_get_bitratelist(priv, &numrates, 314cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->bitrate, IW_MAX_BITRATES); 315cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 316cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 317cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->num_bitrates = numrates; 318cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 319cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Set an indication of the max TCP throughput in bit/s that we can 320cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * expect using this interface. May be use for QoS stuff... 321cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Jean II */ 322cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (numrates > 2) 323cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ 324cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 325cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ 326cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 327cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->min_rts = 0; 328cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_rts = 2347; 329cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->min_frag = 256; 330cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_frag = 2346; 331cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 332cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->min_pmp = 0; 333cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_pmp = 65535000; 334cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->min_pmt = 0; 335cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_pmt = 65535 * 1000; /* ??? */ 336cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->pmp_flags = IW_POWER_PERIOD; 337cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->pmt_flags = IW_POWER_TIMEOUT; 338cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->pm_capa = (IW_POWER_PERIOD | IW_POWER_TIMEOUT | 339cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_POWER_UNICAST_R); 340cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 341cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; 342cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->retry_flags = IW_RETRY_LIMIT; 343cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->r_time_flags = IW_RETRY_LIFETIME; 344cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->min_retry = 0; 345cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_retry = 65535; /* ??? */ 346cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->min_r_time = 0; 347cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->max_r_time = 65535 * 1000; /* ??? */ 348cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 349cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->firmware_type == FIRMWARE_TYPE_AGERE) 350cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->scan_capa = IW_SCAN_CAPA_ESSID; 351cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 352cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy range->scan_capa = IW_SCAN_CAPA_NONE; 353cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 354cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Event capability (kernel) */ 355cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_EVENT_CAPA_SET_KERNEL(range->event_capa); 356cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Event capability (driver) */ 357cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); 358cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); 359cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); 360cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); 361cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 362cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 363cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 364cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 365cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setiwencode(struct net_device *dev, 366cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 367cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *erq, 368cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *keybuf) 369cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 370cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 371cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int index = (erq->flags & IW_ENCODE_INDEX) - 1; 372cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int setindex = priv->tx_key; 373cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int encode_alg = priv->encode_alg; 374cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int restricted = priv->wep_restrict; 375cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 xlen = 0; 376cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = -EINPROGRESS; /* Call commit handler */ 377cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 378cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 379cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_wep) 380cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EOPNOTSUPP; 381cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 382cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->pointer) { 383cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* We actually have a key to set - check its length */ 384cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->length > LARGE_KEY_SIZE) 385cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -E2BIG; 386cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 387cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep) 388cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -E2BIG; 389cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 390cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 391cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 392cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 393cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 394cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Clear any TKIP key we have */ 395cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_ALG_TKIP)) 396cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (void) orinoco_clear_tkip_key(priv, setindex); 397cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 398cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->length > 0) { 399cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) 400cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy index = priv->tx_key; 401cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 402cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Adjust key length to a supported value */ 403cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->length > SMALL_KEY_SIZE) 404cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy xlen = LARGE_KEY_SIZE; 405cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else if (erq->length > 0) 406cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy xlen = SMALL_KEY_SIZE; 407cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 408cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy xlen = 0; 409cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 410cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Switch on WEP if off */ 411cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((encode_alg != IW_ENCODE_ALG_WEP) && (xlen > 0)) { 412cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy setindex = index; 413cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy encode_alg = IW_ENCODE_ALG_WEP; 414cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 415cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 416cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Important note : if the user do "iwconfig eth0 enc off", 417cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * we will arrive there with an index of -1. This is valid 418cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * but need to be taken care off... Jean II */ 419cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) { 420cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((index != -1) || (erq->flags == 0)) { 421cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 422cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 423cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 424cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 425cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Set the index : Check that the key is valid */ 426cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->keys[index].len == 0) { 427cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 428cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 429cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 430cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy setindex = index; 431cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 432cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 433cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 434cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->flags & IW_ENCODE_DISABLED) 435cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy encode_alg = IW_ENCODE_ALG_NONE; 436cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->flags & IW_ENCODE_OPEN) 437cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy restricted = 0; 438cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->flags & IW_ENCODE_RESTRICTED) 439cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy restricted = 1; 440cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 441cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->pointer && erq->length > 0) { 442cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->keys[index].len = cpu_to_le16(xlen); 443cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(priv->keys[index].data, 0, 444cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy sizeof(priv->keys[index].data)); 445cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(priv->keys[index].data, keybuf, erq->length); 446cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 447cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->tx_key = setindex; 448cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 449cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Try fast key change if connected and only keys are changed */ 450cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((priv->encode_alg == encode_alg) && 451cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (priv->wep_restrict == restricted) && 452cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy netif_carrier_ok(dev)) { 453cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = __orinoco_hw_setup_wepkeys(priv); 454cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* No need to commit if successful */ 455cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 456cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 457cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 458cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->encode_alg = encode_alg; 459cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->wep_restrict = restricted; 460cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 461cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 462cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 463cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 464cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 465cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 466cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 467cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getiwencode(struct net_device *dev, 468cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 469cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *erq, 470cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *keybuf) 471cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 472cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 473cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int index = (erq->flags & IW_ENCODE_INDEX) - 1; 474cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 xlen = 0; 475cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 476cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 477cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_wep) 478cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EOPNOTSUPP; 479cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 480cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 481cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 482cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 483cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) 484cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy index = priv->tx_key; 485cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 486cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->flags = 0; 487cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->encode_alg) 488cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->flags |= IW_ENCODE_DISABLED; 489cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->flags |= index + 1; 490cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 491cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->wep_restrict) 492cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->flags |= IW_ENCODE_RESTRICTED; 493cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 494cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->flags |= IW_ENCODE_OPEN; 495cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 496cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy xlen = le16_to_cpu(priv->keys[index].len); 497cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 498cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->length = xlen; 499cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 500cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); 501cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 502cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 503cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 504cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 505cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 506cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setessid(struct net_device *dev, 507cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 508cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *erq, 509cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *essidbuf) 510cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 511cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 512cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 513cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 514cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it 515cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * anyway... - Jean II */ 516cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 517cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Hum... Should not use Wireless Extension constant (may change), 518cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * should use our own... - Jean II */ 519cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->length > IW_ESSID_MAX_SIZE) 520cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -E2BIG; 521cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 522cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 523cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 524cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 525cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ 526cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); 527cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 528cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* If not ANY, get the new ESSID */ 529cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (erq->flags) 530cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(priv->desired_essid, essidbuf, erq->length); 531cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 532cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 533cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 534cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINPROGRESS; /* Call commit handler */ 535cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 536cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 537cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getessid(struct net_device *dev, 538cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 539cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *erq, 540cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *essidbuf) 541cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 542cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 543cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int active; 544cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 545cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 546cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 547cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (netif_running(dev)) { 548cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = orinoco_hw_get_essid(priv, &active, essidbuf); 549cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err < 0) 550cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 551cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->length = err; 552cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 553cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 554cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 555cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE); 556cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->length = strlen(priv->desired_essid); 557cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 558cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 559cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 560cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy erq->flags = 1; 561cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 562cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 563cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 564cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 565cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setnick(struct net_device *dev, 566cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 567cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *nrq, 568cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *nickbuf) 569cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 570cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 571cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 572cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 573cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (nrq->length > IW_ESSID_MAX_SIZE) 574cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -E2BIG; 575cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 576cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 577cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 578cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 579cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(priv->nick, 0, sizeof(priv->nick)); 580cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(priv->nick, nickbuf, nrq->length); 581cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 582cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 583cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 584cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINPROGRESS; /* Call commit handler */ 585cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 586cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 587cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getnick(struct net_device *dev, 588cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 589cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *nrq, 590cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *nickbuf) 591cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 592cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 593cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 594cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 595cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 596cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 597cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 598cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE); 599cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 600cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 601cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy nrq->length = strlen(priv->nick); 602cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 603cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 604cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 605cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 606cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setfreq(struct net_device *dev, 607cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 608cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_freq *frq, 609cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 610cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 611cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 612cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int chan = -1; 613cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 614cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = -EINPROGRESS; /* Call commit handler */ 615cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 616cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* In infrastructure mode the AP sets the channel */ 617cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->iw_mode == IW_MODE_INFRA) 618cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 619cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 620cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((frq->e == 0) && (frq->m <= 1000)) { 621cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Setting by channel number */ 622cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy chan = frq->m; 623cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 624cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Setting by frequency */ 625cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int denom = 1; 626cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int i; 627cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 628cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Calculate denominator to rescale to MHz */ 629cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy for (i = 0; i < (6 - frq->e); i++) 630cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy denom *= 10; 631cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 632cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy chan = ieee80211_freq_to_dsss_chan(frq->m / denom); 633cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 634cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 635cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((chan < 1) || (chan > NUM_CHANNELS) || 636cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy !(priv->channel_mask & (1 << (chan-1)))) 637cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINVAL; 638cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 639cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 640cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 641cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 642cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->channel = chan; 643cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->iw_mode == IW_MODE_MONITOR) { 644cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Fast channel change - no commit if successful */ 645cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 646cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_docmd_wait(hw, HERMES_CMD_TEST | 647cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_TEST_SET_CHANNEL, 648cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy chan, NULL); 649cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 650cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 651cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 652cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 653cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 654cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 655cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getfreq(struct net_device *dev, 656cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 657cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_freq *frq, 658cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 659cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 660cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 661cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int tmp; 662cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 663cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Locking done in there */ 664cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy tmp = orinoco_hw_get_freq(priv); 665cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (tmp < 0) 666cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return tmp; 667cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 668cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->m = tmp * 100000; 669cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->e = 1; 670cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 671cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 672cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 673cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 674cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getsens(struct net_device *dev, 675cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 676cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *srq, 677cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 678cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 679cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 680cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 681cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 val; 682cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err; 683cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 684cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 685cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_sensitivity) 686cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EOPNOTSUPP; 687cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 688cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 689cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 690cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, 691cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFSYSTEMSCALE, &val); 692cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 693cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 694cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 695cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 696cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 697cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy srq->value = val; 698cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy srq->fixed = 0; /* auto */ 699cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 700cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 701cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 702cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 703cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setsens(struct net_device *dev, 704cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 705cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *srq, 706cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 707cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 708cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 709cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int val = srq->value; 710cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 711cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 712cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_sensitivity) 713cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EOPNOTSUPP; 714cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 715cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((val < 1) || (val > 3)) 716cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINVAL; 717cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 718cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 719cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 720cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->ap_density = val; 721cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 722cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 723cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINPROGRESS; /* Call commit handler */ 724cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 725cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 726cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setrts(struct net_device *dev, 727cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 728cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *rrq, 729cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 730cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 731cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 732cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int val = rrq->value; 733cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 734cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 735cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (rrq->disabled) 736cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy val = 2347; 737cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 738cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((val < 0) || (val > 2347)) 739cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINVAL; 740cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 741cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 742cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 743cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 744cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->rts_thresh = val; 745cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 746cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 747cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINPROGRESS; /* Call commit handler */ 748cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 749cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 750cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getrts(struct net_device *dev, 751cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 752cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *rrq, 753cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 754cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 755cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 756cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 757cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->value = priv->rts_thresh; 758cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->disabled = (rrq->value == 2347); 759cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->fixed = 1; 760cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 761cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 762cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 763cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 764cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setfrag(struct net_device *dev, 765cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 766cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *frq, 767cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 768cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 769cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 770cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = -EINPROGRESS; /* Call commit handler */ 771cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 772cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 773cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 774cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 775cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 776cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_mwo) { 777cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (frq->disabled) 778cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->mwo_robust = 0; 779cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else { 780cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (frq->fixed) 781cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Fixed fragmentation " 782cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "is not supported on this firmware. " 783cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "Using MWO robust instead.\n", 784cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy dev->name); 785cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->mwo_robust = 1; 786cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 787cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 788cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (frq->disabled) 789cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->frag_thresh = 2346; 790cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else { 791cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((frq->value < 256) || (frq->value > 2346)) 792cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 793cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 794cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* must be even */ 795cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->frag_thresh = frq->value & ~0x1; 796cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 797cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 798cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 799cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 800cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 801cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 802cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 803cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 804cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getfrag(struct net_device *dev, 805cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 806cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *frq, 807cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 808cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 809cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 810cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 811cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err; 812cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 val; 813cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 814cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 815cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 816cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 817cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 818cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_mwo) { 819cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, 820cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFMWOROBUST_AGERE, 821cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &val); 822cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 823cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy val = 0; 824cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 825cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->value = val ? 2347 : 0; 826cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->disabled = !val; 827cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->fixed = 0; 828cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 829cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, 830cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, 831cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &val); 832cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 833cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy val = 0; 834cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 835cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->value = val; 836cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->disabled = (val >= 2346); 837cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy frq->fixed = 1; 838cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 839cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 840cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 841cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 842cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 843cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 844cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 845cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setrate(struct net_device *dev, 846cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 847cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *rrq, 848cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 849cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 850cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 851cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int ratemode; 852cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int bitrate; /* 100s of kilobits */ 853cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 854cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 855cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* As the user space doesn't know our highest rate, it uses -1 856cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * to ask us to set the highest rate. Test it using "iwconfig 857cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * ethX rate auto" - Jean II */ 858cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (rrq->value == -1) 859cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy bitrate = 110; 860cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else { 861cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (rrq->value % 100000) 862cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINVAL; 863cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy bitrate = rrq->value / 100000; 864cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 865cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 866cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed); 867cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 868cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ratemode == -1) 869cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINVAL; 870cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 871cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 872cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 873cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->bitratemode = ratemode; 874cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 875cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 876cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINPROGRESS; 877cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 878cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 879cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getrate(struct net_device *dev, 880cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 881cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *rrq, 882cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 883cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 884cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 885cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 886cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int bitrate, automatic; 887cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 888cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 889cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 890cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 891cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 892cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic); 893cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 894cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* If the interface is running we try to find more about the 895cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current mode */ 896cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (netif_running(dev)) 897cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = orinoco_hw_get_act_bitrate(priv, &bitrate); 898cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 899cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 900cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 901cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->value = bitrate; 902cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->fixed = !automatic; 903cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->disabled = 0; 904cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 905cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 906cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 907cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 908cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setpower(struct net_device *dev, 909cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 910cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *prq, 911cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 912cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 913cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 914cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = -EINPROGRESS; /* Call commit handler */ 915cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 916cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 917cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 918cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 919cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 920cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (prq->disabled) { 921cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_on = 0; 922cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 923cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (prq->flags & IW_POWER_MODE) { 924cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_POWER_UNICAST_R: 925cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_mcast = 0; 926cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_on = 1; 927cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 928cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_POWER_ALL_R: 929cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_mcast = 1; 930cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_on = 1; 931cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 932cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_POWER_ON: 933cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* No flags : but we may have a value - Jean II */ 934cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 935cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy default: 936cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 937cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 938cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 939cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 940cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (prq->flags & IW_POWER_TIMEOUT) { 941cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_on = 1; 942cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_timeout = prq->value / 1000; 943cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 944cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (prq->flags & IW_POWER_PERIOD) { 945cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_on = 1; 946cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->pm_period = prq->value / 1000; 947cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 948cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* It's valid to not have a value if we are just toggling 949cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * the flags... Jean II */ 950cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->pm_on) { 951cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 952cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 953cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 954cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 955cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 956cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 957cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 958cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 959cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 960cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 961cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 962cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getpower(struct net_device *dev, 963cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 964cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *prq, 965cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 966cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 967cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 968cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 969cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 970cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 enable, period, timeout, mcast; 971cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 972cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 973cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 974cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 975cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 976cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, 977cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFPMENABLED, &enable); 978cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 979cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 980cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 981cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, 982cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFMAXSLEEPDURATION, &period); 983cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 984cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 985cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 986cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, 987cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFPMHOLDOVERDURATION, &timeout); 988cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 989cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 990cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 991cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, 992cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFMULTICASTRECEIVE, &mcast); 993cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 994cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 995cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 996cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy prq->disabled = !enable; 997cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Note : by default, display the period */ 998cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { 999cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy prq->flags = IW_POWER_TIMEOUT; 1000cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy prq->value = timeout * 1000; 1001cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 1002cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy prq->flags = IW_POWER_PERIOD; 1003cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy prq->value = period * 1000; 1004cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1005cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (mcast) 1006cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy prq->flags |= IW_POWER_ALL_R; 1007cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1008cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy prq->flags |= IW_POWER_UNICAST_R; 1009cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1010cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 1011cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1012cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1013cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1014cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1015cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1016cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_set_encodeext(struct net_device *dev, 1017cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1018cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union iwreq_data *wrqu, 1019cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1020cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1021cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1022cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *encoding = &wrqu->encoding; 1023cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1024cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int idx, alg = ext->alg, set_key = 1; 1025cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1026cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = -EINVAL; 1027cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 key_len; 1028cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1029cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1030cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1031cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1032cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Determine and validate the key index */ 1033cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy idx = encoding->flags & IW_ENCODE_INDEX; 1034cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (idx) { 1035cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((idx < 1) || (idx > 4)) 1036cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1037cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy idx--; 1038cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else 1039cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy idx = priv->tx_key; 1040cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1041cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (encoding->flags & IW_ENCODE_DISABLED) 1042cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy alg = IW_ENCODE_ALG_NONE; 1043cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1044cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) { 1045cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Clear any TKIP TX key we had */ 1046cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (void) orinoco_clear_tkip_key(priv, priv->tx_key); 1047cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1048cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1049cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { 1050cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->tx_key = idx; 1051cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy set_key = ((alg == IW_ENCODE_ALG_TKIP) || 1052cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (ext->key_len > 0)) ? 1 : 0; 1053cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1054cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1055cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (set_key) { 1056cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Set the requested key first */ 1057cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (alg) { 1058cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_ENCODE_ALG_NONE: 1059cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->encode_alg = alg; 1060cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->keys[idx].len = 0; 1061cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1062cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1063cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_ENCODE_ALG_WEP: 1064cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ext->key_len > SMALL_KEY_SIZE) 1065cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy key_len = LARGE_KEY_SIZE; 1066cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else if (ext->key_len > 0) 1067cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy key_len = SMALL_KEY_SIZE; 1068cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1069cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1070cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1071cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->encode_alg = alg; 1072cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->keys[idx].len = cpu_to_le16(key_len); 1073cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1074cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy key_len = min(ext->key_len, key_len); 1075cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1076cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE); 1077cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(priv->keys[idx].data, ext->key, key_len); 1078cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1079cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1080cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_ENCODE_ALG_TKIP: 1081cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { 1082cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 1083cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u8 *tkip_iv = NULL; 1084cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1085cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_wpa || 1086cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (ext->key_len > sizeof(priv->tkip_key[0]))) 1087cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1088cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1089cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->encode_alg = alg; 1090cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(&priv->tkip_key[idx], 0, 1091cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy sizeof(priv->tkip_key[idx])); 1092cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(&priv->tkip_key[idx], ext->key, ext->key_len); 1093cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1094cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) 1095cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy tkip_iv = &ext->rx_seq[0]; 1096cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1097cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = __orinoco_hw_set_tkip_key(hw, idx, 1098cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 1099cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (u8 *) &priv->tkip_key[idx], 1100cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy tkip_iv, NULL); 1101cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 1102cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_ERR "%s: Error %d setting TKIP key" 1103cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "\n", dev->name, err); 1104cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1105cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1106cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1107cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy default: 1108cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1109cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1110cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1111cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINPROGRESS; 1112cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 1113cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1114cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1115cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1116cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1117cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1118cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_get_encodeext(struct net_device *dev, 1119cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1120cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union iwreq_data *wrqu, 1121cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1122cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1123cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1124cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *encoding = &wrqu->encoding; 1125cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1126cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int idx, max_key_len; 1127cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1128cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err; 1129cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1130cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1131cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1132cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1133cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 1134cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy max_key_len = encoding->length - sizeof(*ext); 1135cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (max_key_len < 0) 1136cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1137cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1138cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy idx = encoding->flags & IW_ENCODE_INDEX; 1139cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (idx) { 1140cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((idx < 1) || (idx > 4)) 1141cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1142cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy idx--; 1143cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else 1144cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy idx = priv->tx_key; 1145cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1146cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy encoding->flags = idx + 1; 1147cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(ext, 0, sizeof(*ext)); 1148cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1149cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ext->alg = priv->encode_alg; 1150cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (priv->encode_alg) { 1151cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_ENCODE_ALG_NONE: 1152cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ext->key_len = 0; 1153cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy encoding->flags |= IW_ENCODE_DISABLED; 1154cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1155cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_ENCODE_ALG_WEP: 1156cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len), 1157cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy max_key_len); 1158cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(ext->key, priv->keys[idx].data, ext->key_len); 1159cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy encoding->flags |= IW_ENCODE_ENABLED; 1160cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1161cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_ENCODE_ALG_TKIP: 1162cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key), 1163cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy max_key_len); 1164cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(ext->key, &priv->tkip_key[idx], ext->key_len); 1165cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy encoding->flags |= IW_ENCODE_ENABLED; 1166cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1167cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1168cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1169cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = 0; 1170cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 1171cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1172cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1173cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1174cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1175cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1176cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_set_auth(struct net_device *dev, 1177cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1178cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union iwreq_data *wrqu, char *extra) 1179cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1180cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1181cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 1182cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *param = &wrqu->param; 1183cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1184cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int ret = -EINPROGRESS; 1185cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1186cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1187cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1188cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1189cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (param->flags & IW_AUTH_INDEX) { 1190cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_WPA_VERSION: 1191cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_CIPHER_PAIRWISE: 1192cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_CIPHER_GROUP: 1193cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_RX_UNENCRYPTED_EAPOL: 1194cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_PRIVACY_INVOKED: 1195cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_DROP_UNENCRYPTED: 1196cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* 1197cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * orinoco does not use these parameters 1198cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy */ 1199cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1200cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1201cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_KEY_MGMT: 1202cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* wl_lkm implies value 2 == PSK for Hermes I 1203cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * which ties in with WEXT 1204cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * no other hints tho :( 1205cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy */ 1206cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->key_mgmt = param->value; 1207cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1208cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1209cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_TKIP_COUNTERMEASURES: 1210cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* When countermeasures are enabled, shut down the 1211cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * card; when disabled, re-enable the card. This must 1212cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * take effect immediately. 1213cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * 1214cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * TODO: Make sure that the EAPOL message is getting 1215cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * out before card disabled 1216cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy */ 1217cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (param->value) { 1218cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->tkip_cm_active = 1; 1219cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = hermes_enable_port(hw, 0); 1220cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 1221cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->tkip_cm_active = 0; 1222cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = hermes_disable_port(hw, 0); 1223cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1224cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1225cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1226cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_80211_AUTH_ALG: 1227cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (param->value & IW_AUTH_ALG_SHARED_KEY) 1228cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->wep_restrict = 1; 1229cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) 1230cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->wep_restrict = 0; 1231cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1232cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = -EINVAL; 1233cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1234cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1235cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_WPA_ENABLED: 1236cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_wpa) { 1237cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->wpa_enabled = param->value ? 1 : 0; 1238cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 1239cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (param->value) 1240cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = -EOPNOTSUPP; 1241cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* else silently accept disable of WPA */ 1242cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->wpa_enabled = 0; 1243cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1244cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1245cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1246cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy default: 1247cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = -EOPNOTSUPP; 1248cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1249cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1250cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1251cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return ret; 1252cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1253cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1254cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_get_auth(struct net_device *dev, 1255cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1256cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union iwreq_data *wrqu, char *extra) 1257cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1258cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1259cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *param = &wrqu->param; 1260cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1261cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int ret = 0; 1262cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1263cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1264cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1265cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1266cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (param->flags & IW_AUTH_INDEX) { 1267cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_KEY_MGMT: 1268cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy param->value = priv->key_mgmt; 1269cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1270cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1271cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_TKIP_COUNTERMEASURES: 1272cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy param->value = priv->tkip_cm_active; 1273cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1274cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1275cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_80211_AUTH_ALG: 1276cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->wep_restrict) 1277cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy param->value = IW_AUTH_ALG_SHARED_KEY; 1278cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1279cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy param->value = IW_AUTH_ALG_OPEN_SYSTEM; 1280cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1281cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1282cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_AUTH_WPA_ENABLED: 1283cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy param->value = priv->wpa_enabled; 1284cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1285cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1286cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy default: 1287cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = -EOPNOTSUPP; 1288cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1289cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1290cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1291cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return ret; 1292cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1293cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1294cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_set_genie(struct net_device *dev, 1295cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1296cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union iwreq_data *wrqu, char *extra) 1297cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1298cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1299cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u8 *buf; 1300cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1301cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1302cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* cut off at IEEE80211_MAX_DATA_LEN */ 1303cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) || 1304cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (wrqu->data.length && (extra == NULL))) 1305cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINVAL; 1306cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1307cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (wrqu->data.length) { 1308cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy buf = kmalloc(wrqu->data.length, GFP_KERNEL); 1309cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (buf == NULL) 1310cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -ENOMEM; 1311cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1312cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(buf, extra, wrqu->data.length); 1313cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else 1314cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy buf = NULL; 1315cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1316cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) { 1317cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy kfree(buf); 1318cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1319cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1320cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1321cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy kfree(priv->wpa_ie); 1322cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->wpa_ie = buf; 1323cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->wpa_ie_len = wrqu->data.length; 1324cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1325cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->wpa_ie) { 1326cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Looks like wl_lkm wants to check the auth alg, and 1327cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * somehow pass it to the firmware. 1328cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Instead it just calls the key mgmt rid 1329cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * - we do this in set auth. 1330cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy */ 1331cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1332cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1333cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1334cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 1335cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1336cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1337cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_get_genie(struct net_device *dev, 1338cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1339cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union iwreq_data *wrqu, char *extra) 1340cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1341cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1342cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1343cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 1344cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1345cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1346cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1347cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1348cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) { 1349cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wrqu->data.length = 0; 1350cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1351cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1352cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1353cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (wrqu->data.length < priv->wpa_ie_len) { 1354cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -E2BIG; 1355cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1356cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1357cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1358cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy wrqu->data.length = priv->wpa_ie_len; 1359cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(extra, priv->wpa_ie, priv->wpa_ie_len); 1360cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1361cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroyout: 1362cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1363cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1364cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1365cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1366cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_set_mlme(struct net_device *dev, 1367cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1368cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union iwreq_data *wrqu, char *extra) 1369cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1370cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1371cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 1372cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_mlme *mlme = (struct iw_mlme *)extra; 1373cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1374cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int ret = 0; 1375cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1376cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1377cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1378cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1379cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (mlme->cmd) { 1380cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_MLME_DEAUTH: 1381cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* silently ignore */ 1382cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1383cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1384cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case IW_MLME_DISASSOC: 1385cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { 1386cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct { 1387cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u8 addr[ETH_ALEN]; 1388cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy __le16 reason_code; 1389cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } __attribute__ ((packed)) buf; 1390cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1391cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(buf.addr, mlme->addr.sa_data, ETH_ALEN); 1392cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy buf.reason_code = cpu_to_le16(mlme->reason_code); 1393cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = HERMES_WRITE_RECORD(hw, USER_BAP, 1394cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFDISASSOCIATE, 1395cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &buf); 1396cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1397cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1398cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy default: 1399cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ret = -EOPNOTSUPP; 1400cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1401cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1402cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1403cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return ret; 1404cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1405cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1406cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getretry(struct net_device *dev, 1407cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1408cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_param *rrq, 1409cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1410cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1411cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1412cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 1413cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 1414cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 short_limit, long_limit, lifetime; 1415cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1416cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1417cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1418cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1419cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1420cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT, 1421cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &short_limit); 1422cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 1423cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1424cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1425cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT, 1426cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &long_limit); 1427cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 1428cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1429cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1430cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME, 1431cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &lifetime); 1432cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 1433cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1434cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1435cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->disabled = 0; /* Can't be disabled */ 1436cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1437cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Note : by default, display the retry number */ 1438cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { 1439cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->flags = IW_RETRY_LIFETIME; 1440cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->value = lifetime * 1000; /* ??? */ 1441cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 1442cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* By default, display the min number */ 1443cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((rrq->flags & IW_RETRY_LONG)) { 1444cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; 1445cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->value = long_limit; 1446cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 1447cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->flags = IW_RETRY_LIMIT; 1448cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->value = short_limit; 1449cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (short_limit != long_limit) 1450cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy rrq->flags |= IW_RETRY_SHORT; 1451cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1452cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1453cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1454cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 1455cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1456cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1457cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1458cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1459cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1460cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_reset(struct net_device *dev, 1461cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1462cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 1463cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1464cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1465cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1466cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1467cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!capable(CAP_NET_ADMIN)) 1468cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EPERM; 1469cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1470cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) { 1471cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); 1472cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1473cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Firmware reset */ 1474cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_reset(&priv->reset_work); 1475cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 1476cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); 1477cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1478cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy schedule_work(&priv->reset_work); 1479cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1480cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1481cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 1482cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1483cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1484cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setibssport(struct net_device *dev, 1485cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1486cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 1487cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1488cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1489cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1490cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1491cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int val = *((int *) extra); 1492cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1493cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1494cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1495cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1496cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1497cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->ibss_port = val ; 1498cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1499cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Actually update the mode we are using */ 1500cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy set_port_type(priv); 1501cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1502cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1503cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINPROGRESS; /* Call commit handler */ 1504cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1505cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1506cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getibssport(struct net_device *dev, 1507cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1508cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 1509cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1510cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1511cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1512cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int *val = (int *) extra; 1513cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1514cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy *val = priv->ibss_port; 1515cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 1516cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1517cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1518cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setport3(struct net_device *dev, 1519cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1520cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 1521cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1522cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1523cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1524cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int val = *((int *) extra); 1525cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 1526cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1527cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1528cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1529cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1530cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1531cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (val) { 1532cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case 0: /* Try to do IEEE ad-hoc mode */ 1533cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_ibss) { 1534cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 1535cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1536cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1537cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->prefer_port3 = 0; 1538cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1539cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1540cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1541cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case 1: /* Try to do Lucent proprietary ad-hoc mode */ 1542cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_port3) { 1543cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 1544cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1545cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1546cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->prefer_port3 = 1; 1547cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1548cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1549cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy default: 1550cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINVAL; 1551cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1552cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1553cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!err) { 1554cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Actually update the mode we are using */ 1555cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy set_port_type(priv); 1556cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EINPROGRESS; 1557cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1558cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1559cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1560cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1561cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1562cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1563cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1564cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getport3(struct net_device *dev, 1565cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1566cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 1567cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1568cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1569cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1570cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int *val = (int *) extra; 1571cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1572cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy *val = priv->prefer_port3; 1573cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 1574cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1575cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1576cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setpreamble(struct net_device *dev, 1577cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1578cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 1579cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1580cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1581cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1582cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1583cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int val; 1584cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1585cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_preamble) 1586cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EOPNOTSUPP; 1587cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1588cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* 802.11b has recently defined some short preamble. 1589cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Basically, the Phy header has been reduced in size. 1590cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * This increase performance, especially at high rates 1591cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * (the preamble is transmitted at 1Mb/s), unfortunately 1592cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * this give compatibility troubles... - Jean II */ 1593cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy val = *((int *) extra); 1594cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1595cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1596cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1597cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1598cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (val) 1599cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->preamble = 1; 1600cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1601cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->preamble = 0; 1602cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1603cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1604cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1605cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINPROGRESS; /* Call commit handler */ 1606cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1607cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1608cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getpreamble(struct net_device *dev, 1609cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1610cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 1611cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1612cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1613cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1614cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int *val = (int *) extra; 1615cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1616cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->has_preamble) 1617cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EOPNOTSUPP; 1618cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1619cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy *val = priv->preamble; 1620cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 1621cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1622cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1623cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* ioctl interface to hermes_read_ltv() 1624cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * To use with iwpriv, pass the RID as the token argument, e.g. 1625cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * iwpriv get_rid [0xfc00] 1626cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * At least Wireless Tools 25 is required to use iwpriv. 1627cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * For Wireless Tools 25 and 26 append "dummy" are the end. */ 1628cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getrid(struct net_device *dev, 1629cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1630cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *data, 1631cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1632cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1633cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1634cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 1635cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int rid = data->flags; 1636cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 length; 1637cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err; 1638cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1639cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1640cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* It's a "get" function, but we don't want users to access the 1641cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * WEP key and other raw firmware data */ 1642cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!capable(CAP_NET_ADMIN)) 1643cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EPERM; 1644cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1645cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (rid < 0xfc00 || rid > 0xffff) 1646cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EINVAL; 1647cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1648cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1649cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1650cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1651cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, 1652cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy extra); 1653cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 1654cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1655cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1656cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), 1657cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy MAX_RID_LEN); 1658cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1659cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 1660cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1661cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1662cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1663cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1664cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* Trigger a scan (look for other cells in the vicinity) */ 1665cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_setscan(struct net_device *dev, 1666cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1667cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *srq, 1668cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 1669cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1670cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1671cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy hermes_t *hw = &priv->hw; 1672cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_scan_req *si = (struct iw_scan_req *) extra; 1673cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 1674cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 1675cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1676cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Note : you may have realised that, as this is a SET operation, 1677cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * this is privileged and therefore a normal user can't 1678cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * perform scanning. 1679cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * This is not an error, while the device perform scanning, 1680cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * traffic doesn't flow, so it's a perfect DoS... 1681cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Jean II */ 1682cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1683cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 1684cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 1685cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1686cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Scanning with port 0 disabled would fail */ 1687cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!netif_running(dev)) { 1688cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -ENETDOWN; 1689cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1690cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1691cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1692cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* In monitor mode, the scan results are always empty. 1693cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Probe responses are passed to the driver as received 1694cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * frames and could be processed in software. */ 1695cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->iw_mode == IW_MODE_MONITOR) { 1696cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EOPNOTSUPP; 1697cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1698cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1699cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1700cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Note : because we don't lock out the irq handler, the way 1701cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * we access scan variables in priv is critical. 1702cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * o scan_inprogress : not touched by irq handler 1703cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * o scan_mode : not touched by irq handler 1704cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Before modifying anything on those variables, please think hard ! 1705cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Jean II */ 1706cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1707cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Save flags */ 1708cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->scan_mode = srq->flags; 1709cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1710cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Always trigger scanning, even if it's in progress. 1711cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * This way, if the info frame get lost, we will recover somewhat 1712cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * gracefully - Jean II */ 1713cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1714cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_hostscan) { 1715cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy switch (priv->firmware_type) { 1716cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case FIRMWARE_TYPE_SYMBOL: 1717cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_write_wordrec(hw, USER_BAP, 1718cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFHOSTSCAN_SYMBOL, 1719cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_HOSTSCAN_SYMBOL_ONCE | 1720cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_HOSTSCAN_SYMBOL_BCAST); 1721cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1722cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case FIRMWARE_TYPE_INTERSIL: { 1723cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy __le16 req[3]; 1724cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1725cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy req[0] = cpu_to_le16(0x3fff); /* All channels */ 1726cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ 1727cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy req[2] = 0; /* Any ESSID */ 1728cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = HERMES_WRITE_RECORD(hw, USER_BAP, 1729cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFHOSTSCAN, &req); 1730cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1731cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1732cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy case FIRMWARE_TYPE_AGERE: 1733cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->scan_mode & IW_SCAN_THIS_ESSID) { 1734cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct hermes_idstring idbuf; 1735cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy size_t len = min(sizeof(idbuf.val), 1736cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (size_t) si->essid_len); 1737cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy idbuf.len = cpu_to_le16(len); 1738cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(idbuf.val, si->essid, len); 1739cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1740cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_write_ltv(hw, USER_BAP, 1741cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFSCANSSID_AGERE, 1742cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_BYTES_TO_RECLEN(len + 2), 1743cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &idbuf); 1744cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else 1745cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_write_wordrec(hw, USER_BAP, 1746cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFSCANSSID_AGERE, 1747cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 0); /* Any ESSID */ 1748cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 1749cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1750cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1751cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_ext_scan) { 1752cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Clear scan results at the start of 1753cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * an extended scan */ 1754cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_clear_scan_results(priv, 1755cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy msecs_to_jiffies(15000)); 1756cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1757cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* TODO: Is this available on older firmware? 1758cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Can we use it to scan specific channels 1759cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * for IW_SCAN_THIS_FREQ? */ 1760cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_write_wordrec(hw, USER_BAP, 1761cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_RID_CNFSCANCHANNELS2GHZ, 1762cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 0x7FFF); 1763cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) 1764cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 1765cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1766cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_inquire(hw, 1767cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy HERMES_INQ_CHANNELINFO); 1768cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else 1769cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_inquire(hw, HERMES_INQ_SCAN); 1770cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1771cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1772cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else 1773cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_inquire(hw, HERMES_INQ_SCAN); 1774cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1775cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* One more client */ 1776cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!err) 1777cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->scan_inprogress = 1; 1778cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1779cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 1780cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 1781cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 1782cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1783cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1784cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#define MAX_CUSTOM_LEN 64 1785cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1786cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* Translate scan data returned from the card to a card independant 1787cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * format that the Wireless Tools will understand - Jean II */ 1788cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic inline char *orinoco_translate_scan(struct net_device *dev, 1789cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1790cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *current_ev, 1791cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *end_buf, 1792cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy union hermes_scan_info *bss, 1793cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long last_scanned) 1794cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1795cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 1796cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 capabilities; 1797cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 channel; 1798cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_event iwe; /* Temporary buffer */ 1799cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char custom[MAX_CUSTOM_LEN]; 1800cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1801cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(&iwe, 0, sizeof(iwe)); 1802cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1803cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* First entry *MUST* be the AP MAC address */ 1804cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWAP; 1805cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 1806cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN); 1807cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1808cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_ADDR_LEN); 1809cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1810cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Other entries will be displayed in the order we give them */ 1811cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1812cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add the ESSID */ 1813cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = le16_to_cpu(bss->a.essid_len); 1814cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length > 32) 1815cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = 32; 1816cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWESSID; 1817cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.flags = 1; 1818cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1819cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, bss->a.essid); 1820cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1821cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add mode */ 1822cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWMODE; 1823cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy capabilities = le16_to_cpu(bss->a.capabilities); 1824cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { 1825cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (capabilities & WLAN_CAPABILITY_ESS) 1826cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.mode = IW_MODE_MASTER; 1827cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1828cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.mode = IW_MODE_ADHOC; 1829cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1830cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_UINT_LEN); 1831cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1832cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1833cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy channel = bss->s.channel; 1834cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((channel >= 1) && (channel <= NUM_CHANNELS)) { 1835cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add channel and frequency */ 1836cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWFREQ; 1837cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.m = channel; 1838cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.e = 0; 1839cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1840cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_FREQ_LEN); 1841cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1842cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000; 1843cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.e = 1; 1844cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1845cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_FREQ_LEN); 1846cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1847cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1848cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add quality statistics. level and noise in dB. No link quality */ 1849cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVQUAL; 1850cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID; 1851cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95; 1852cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95; 1853cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Wireless tools prior to 27.pre22 will show link quality 1854cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * anyway, so we provide a reasonable value. */ 1855cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.qual.level > iwe.u.qual.noise) 1856cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; 1857cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1858cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.qual = 0; 1859cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1860cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_QUAL_LEN); 1861cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1862cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add encryption capability */ 1863cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWENCODE; 1864cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (capabilities & WLAN_CAPABILITY_PRIVACY) 1865cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 1866cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1867cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.flags = IW_ENCODE_DISABLED; 1868cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = 0; 1869cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1870cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, NULL); 1871cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1872cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Bit rate is not available in Lucent/Agere firmwares */ 1873cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { 1874cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *current_val = current_ev + iwe_stream_lcp_len(info); 1875cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int i; 1876cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int step; 1877cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1878cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) 1879cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy step = 2; 1880cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1881cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy step = 1; 1882cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1883cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWRATE; 1884cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Those two flags are ignored... */ 1885cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; 1886cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Max 10 values */ 1887cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy for (i = 0; i < 10; i += step) { 1888cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* NULL terminated */ 1889cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (bss->p.rates[i] == 0x0) 1890cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy break; 1891cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Bit rate given in 500 kb/s units (+ 0x80) */ 1892cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.bitrate.value = 1893cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ((bss->p.rates[i] & 0x7f) * 500000); 1894cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_val = iwe_stream_add_value(info, current_ev, 1895cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_val, 1896cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy end_buf, &iwe, 1897cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy IW_EV_PARAM_LEN); 1898cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1899cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Check if we added any event */ 1900cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((current_val - current_ev) > iwe_stream_lcp_len(info)) 1901cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = current_val; 1902cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1903cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1904cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Beacon interval */ 1905cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVCUSTOM; 1906cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 1907cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "bcn_int=%d", 1908cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy le16_to_cpu(bss->a.beacon_interv)); 1909cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) 1910cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1911cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, custom); 1912cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1913cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Capabilites */ 1914cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVCUSTOM; 1915cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 1916cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "capab=0x%04x", 1917cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy capabilities); 1918cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) 1919cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1920cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, custom); 1921cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1922cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add EXTRA: Age to display seconds since last beacon/probe response 1923cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * for given network. */ 1924cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVCUSTOM; 1925cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 1926cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy " Last beacon: %dms ago", 1927cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy jiffies_to_msecs(jiffies - last_scanned)); 1928cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) 1929cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1930cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, custom); 1931cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1932cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return current_ev; 1933cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 1934cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1935cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic inline char *orinoco_translate_ext_scan(struct net_device *dev, 1936cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 1937cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *current_ev, 1938cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *end_buf, 1939cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct agere_ext_scan_info *bss, 1940cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long last_scanned) 1941cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 1942cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 capabilities; 1943cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u16 channel; 1944cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_event iwe; /* Temporary buffer */ 1945cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char custom[MAX_CUSTOM_LEN]; 1946cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy u8 *ie; 1947cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1948cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memset(&iwe, 0, sizeof(iwe)); 1949cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1950cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* First entry *MUST* be the AP MAC address */ 1951cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWAP; 1952cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.ap_addr.sa_family = ARPHRD_ETHER; 1953cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); 1954cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1955cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_ADDR_LEN); 1956cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1957cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Other entries will be displayed in the order we give them */ 1958cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1959cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add the ESSID */ 1960cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ie = bss->data; 1961cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = ie[1]; 1962cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) { 1963cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length > 32) 1964cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = 32; 1965cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWESSID; 1966cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.flags = 1; 1967cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1968cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, &ie[2]); 1969cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1970cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1971cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add mode */ 1972cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy capabilities = le16_to_cpu(bss->capabilities); 1973cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { 1974cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWMODE; 1975cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (capabilities & WLAN_CAPABILITY_ESS) 1976cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.mode = IW_MODE_MASTER; 1977cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 1978cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.mode = IW_MODE_ADHOC; 1979cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1980cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_UINT_LEN); 1981cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1982cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1983cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS); 1984cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy channel = ie ? ie[2] : 0; 1985cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((channel >= 1) && (channel <= NUM_CHANNELS)) { 1986cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add channel and frequency */ 1987cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWFREQ; 1988cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.m = channel; 1989cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.e = 0; 1990cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1991cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_FREQ_LEN); 1992cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1993cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000; 1994cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.freq.e = 1; 1995cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 1996cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_FREQ_LEN); 1997cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 1998cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 1999cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add quality statistics. level and noise in dB. No link quality */ 2000cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVQUAL; 2001cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID; 2002cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.level = bss->level - 0x95; 2003cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.noise = bss->noise - 0x95; 2004cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Wireless tools prior to 27.pre22 will show link quality 2005cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * anyway, so we provide a reasonable value. */ 2006cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.qual.level > iwe.u.qual.noise) 2007cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; 2008cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 2009cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.qual.qual = 0; 2010cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_event(info, current_ev, end_buf, 2011cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_QUAL_LEN); 2012cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2013cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add encryption capability */ 2014cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWENCODE; 2015cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (capabilities & WLAN_CAPABILITY_PRIVACY) 2016cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; 2017cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy else 2018cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.flags = IW_ENCODE_DISABLED; 2019cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = 0; 2020cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2021cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, NULL); 2022cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2023cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* WPA IE */ 2024cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data)); 2025cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ie) { 2026cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVGENIE; 2027cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = ie[1] + 2; 2028cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2029cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, ie); 2030cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2031cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2032cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* RSN IE */ 2033cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN); 2034cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ie) { 2035cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVGENIE; 2036cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = ie[1] + 2; 2037cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2038cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, ie); 2039cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2040cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2041cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES); 2042cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (ie) { 2043cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *p = current_ev + iwe_stream_lcp_len(info); 2044cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int i; 2045cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2046cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = SIOCGIWRATE; 2047cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Those two flags are ignored... */ 2048cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; 2049cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2050cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy for (i = 2; i < (ie[1] + 2); i++) { 2051cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000); 2052cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy p = iwe_stream_add_value(info, current_ev, p, end_buf, 2053cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, IW_EV_PARAM_LEN); 2054cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2055cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Check if we added any event */ 2056cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (p > (current_ev + iwe_stream_lcp_len(info))) 2057cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = p; 2058cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2059cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2060cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Timestamp */ 2061cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVCUSTOM; 2062cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = 2063cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx", 2064cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy (unsigned long long) le64_to_cpu(bss->timestamp)); 2065cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) 2066cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2067cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, custom); 2068cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2069cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Beacon interval */ 2070cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVCUSTOM; 2071cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 2072cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "bcn_int=%d", 2073cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy le16_to_cpu(bss->beacon_interval)); 2074cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) 2075cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2076cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, custom); 2077cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2078cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Capabilites */ 2079cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVCUSTOM; 2080cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 2081cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "capab=0x%04x", 2082cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy capabilities); 2083cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) 2084cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2085cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, custom); 2086cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2087cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Add EXTRA: Age to display seconds since last beacon/probe response 2088cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * for given network. */ 2089cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.cmd = IWEVCUSTOM; 2090cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN, 2091cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy " Last beacon: %dms ago", 2092cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy jiffies_to_msecs(jiffies - last_scanned)); 2093cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (iwe.u.data.length) 2094cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = iwe_stream_add_point(info, current_ev, end_buf, 2095cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &iwe, custom); 2096cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2097cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return current_ev; 2098cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 2099cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2100cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* Return results of a scan */ 2101cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_getscan(struct net_device *dev, 2102cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 2103cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_point *srq, 2104cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 2105cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 2106cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 2107cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 2108cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 2109cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *current_ev = extra; 2110cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2111cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 2112cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return -EBUSY; 2113cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2114cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->scan_inprogress) { 2115cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Important note : we don't want to block the caller 2116cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * until results are ready for various reasons. 2117cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * First, managing wait queues is complex and racy. 2118cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Second, we grab some rtnetlink lock before comming 2119cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * here (in dev_ioctl()). 2120cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Third, we generate an Wireless Event, so the 2121cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * caller can wait itself on that - Jean II */ 2122cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -EAGAIN; 2123cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 2124cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2125cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2126cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->has_ext_scan) { 2127cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct xbss_element *bss; 2128cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2129cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy list_for_each_entry(bss, &priv->bss_list, list) { 2130cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Translate this entry to WE format */ 2131cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = 2132cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_translate_ext_scan(dev, info, 2133cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev, 2134cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy extra + srq->length, 2135cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &bss->bss, 2136cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy bss->last_scanned); 2137cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2138cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Check if there is space for one more entry */ 2139cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((extra + srq->length - current_ev) 2140cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy <= IW_EV_ADDR_LEN) { 2141cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Ask user space to try again with a 2142cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * bigger buffer */ 2143cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -E2BIG; 2144cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 2145cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2146cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2147cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2148cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } else { 2149cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct bss_element *bss; 2150cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2151cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy list_for_each_entry(bss, &priv->bss_list, list) { 2152cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Translate this entry to WE format */ 2153cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev = orinoco_translate_scan(dev, info, 2154cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy current_ev, 2155cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy extra + srq->length, 2156cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy &bss->bss, 2157cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy bss->last_scanned); 2158cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2159cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Check if there is space for one more entry */ 2160cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if ((extra + srq->length - current_ev) 2161cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy <= IW_EV_ADDR_LEN) { 2162cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy /* Ask user space to try again with a 2163cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * bigger buffer */ 2164cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = -E2BIG; 2165cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 2166cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2167cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2168cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2169cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2170cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy srq->length = (current_ev - extra); 2171cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy srq->flags = (__u16) priv->scan_mode; 2172cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2173cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroyout: 2174cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 2175cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 2176cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 2177cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2178cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* Commit handler, called after set operations */ 2179cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic int orinoco_ioctl_commit(struct net_device *dev, 2180cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct iw_request_info *info, 2181cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy void *wrqu, 2182cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy char *extra) 2183cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy{ 2184cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct orinoco_private *priv = netdev_priv(dev); 2185cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy struct hermes *hw = &priv->hw; 2186cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy unsigned long flags; 2187cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy int err = 0; 2188cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2189cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (!priv->open) 2190cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 2191cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2192cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (priv->broken_disableport) { 2193cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_reset(&priv->reset_work); 2194cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return 0; 2195cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2196cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2197cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (orinoco_lock(priv, &flags) != 0) 2198cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 2199cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2200cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_disable_port(hw, 0); 2201cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) { 2202cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Unable to disable port " 2203cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "while reconfiguring card\n", dev->name); 2204cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy priv->broken_disableport = 1; 2205cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 2206cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2207cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2208cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = __orinoco_program_rids(dev); 2209cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) { 2210cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Unable to reconfigure card\n", 2211cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy dev->name); 2212cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 2213cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2214cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2215cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = hermes_enable_port(hw, 0); 2216cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) { 2217cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", 2218cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy dev->name); 2219cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy goto out; 2220cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2221cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2222cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy out: 2223cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy if (err) { 2224cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); 2225cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy schedule_work(&priv->reset_work); 2226cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy err = 0; 2227cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy } 2228cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2229cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy orinoco_unlock(priv, &flags); 2230cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy return err; 2231cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy} 2232cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2233cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic const struct iw_priv_args orinoco_privtab[] = { 2234cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, 2235cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, 2236cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 2237cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 0, "set_port3" }, 2238cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 2239cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "get_port3" }, 2240cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 2241cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 0, "set_preamble" }, 2242cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 2243cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "get_preamble" }, 2244cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 2245cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 0, "set_ibssport" }, 2246cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 2247cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "get_ibssport" }, 2248cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN, 2249cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy "get_rid" }, 2250cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy}; 2251cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2252cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2253cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* 2254cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy * Structures to export the Wireless Handlers 2255cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy */ 2256cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2257cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy#define STD_IW_HANDLER(id, func) \ 2258cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [IW_IOCTL_IDX(id)] = (iw_handler) func 2259cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic const iw_handler orinoco_handler[] = { 2260cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit), 2261cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWNAME, orinoco_ioctl_getname), 2262cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq), 2263cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq), 2264cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWMODE, orinoco_ioctl_setmode), 2265cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWMODE, orinoco_ioctl_getmode), 2266cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens), 2267cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens), 2268cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWRANGE, orinoco_ioctl_getiwrange), 2269cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), 2270cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), 2271cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), 2272cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), 2273cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap), 2274cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap), 2275cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWSCAN, orinoco_ioctl_setscan), 2276cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWSCAN, orinoco_ioctl_getscan), 2277cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid), 2278cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid), 2279cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWNICKN, orinoco_ioctl_setnick), 2280cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWNICKN, orinoco_ioctl_getnick), 2281cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate), 2282cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate), 2283cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts), 2284cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWRTS, orinoco_ioctl_getrts), 2285cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag), 2286cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag), 2287cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry), 2288cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode), 2289cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode), 2290cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower), 2291cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower), 2292cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie), 2293cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie), 2294cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme), 2295cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth), 2296cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth), 2297cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext), 2298cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext), 2299cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy}; 2300cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2301cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2302cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy/* 2303cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy Added typecasting since we no longer use iwreq_data -- Moustafa 2304cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy */ 2305cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroystatic const iw_handler orinoco_private_handler[] = { 2306cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [0] = (iw_handler) orinoco_ioctl_reset, 2307cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [1] = (iw_handler) orinoco_ioctl_reset, 2308cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [2] = (iw_handler) orinoco_ioctl_setport3, 2309cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [3] = (iw_handler) orinoco_ioctl_getport3, 2310cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [4] = (iw_handler) orinoco_ioctl_setpreamble, 2311cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [5] = (iw_handler) orinoco_ioctl_getpreamble, 2312cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [6] = (iw_handler) orinoco_ioctl_setibssport, 2313cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [7] = (iw_handler) orinoco_ioctl_getibssport, 2314cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy [9] = (iw_handler) orinoco_ioctl_getrid, 2315cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy}; 2316cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy 2317cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroyconst struct iw_handler_def orinoco_handler_def = { 2318cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy .num_standard = ARRAY_SIZE(orinoco_handler), 2319cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy .num_private = ARRAY_SIZE(orinoco_private_handler), 2320cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy .num_private_args = ARRAY_SIZE(orinoco_privtab), 2321cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy .standard = orinoco_handler, 2322cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy .private = orinoco_private_handler, 2323cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy .private_args = orinoco_privtab, 2324cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy .get_wireless_stats = orinoco_get_wireless_stats, 2325cb1576a829826d56fab59e22aa3af8c5a7db9936David Kilroy}; 2326