1/* cfg80211 support 2 * 3 * See copyright notice in main.c 4 */ 5#include <linux/ieee80211.h> 6#include <net/cfg80211.h> 7#include "hw.h" 8#include "main.h" 9#include "orinoco.h" 10 11#include "cfg.h" 12 13/* Supported bitrates. Must agree with hw.c */ 14static struct ieee80211_rate orinoco_rates[] = { 15 { .bitrate = 10 }, 16 { .bitrate = 20 }, 17 { .bitrate = 55 }, 18 { .bitrate = 110 }, 19}; 20 21static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid; 22 23/* Called after orinoco_private is allocated. */ 24void orinoco_wiphy_init(struct wiphy *wiphy) 25{ 26 struct orinoco_private *priv = wiphy_priv(wiphy); 27 28 wiphy->privid = orinoco_wiphy_privid; 29 30 set_wiphy_dev(wiphy, priv->dev); 31} 32 33/* Called after firmware is initialised */ 34int orinoco_wiphy_register(struct wiphy *wiphy) 35{ 36 struct orinoco_private *priv = wiphy_priv(wiphy); 37 int i, channels = 0; 38 39 if (priv->firmware_type == FIRMWARE_TYPE_AGERE) 40 wiphy->max_scan_ssids = 1; 41 else 42 wiphy->max_scan_ssids = 0; 43 44 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 45 46 /* TODO: should we set if we only have demo ad-hoc? 47 * (priv->has_port3) 48 */ 49 if (priv->has_ibss) 50 wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); 51 52 if (!priv->broken_monitor || force_monitor) 53 wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 54 55 priv->band.bitrates = orinoco_rates; 56 priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates); 57 58 /* Only support channels allowed by the card EEPROM */ 59 for (i = 0; i < NUM_CHANNELS; i++) { 60 if (priv->channel_mask & (1 << i)) { 61 priv->channels[i].center_freq = 62 ieee80211_dsss_chan_to_freq(i+1); 63 channels++; 64 } 65 } 66 priv->band.channels = priv->channels; 67 priv->band.n_channels = channels; 68 69 wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; 70 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 71 72 i = 0; 73 if (priv->has_wep) { 74 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40; 75 i++; 76 77 if (priv->has_big_wep) { 78 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104; 79 i++; 80 } 81 } 82 if (priv->has_wpa) { 83 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP; 84 i++; 85 } 86 wiphy->cipher_suites = priv->cipher_suites; 87 wiphy->n_cipher_suites = i; 88 89 wiphy->rts_threshold = priv->rts_thresh; 90 if (!priv->has_mwo) 91 wiphy->frag_threshold = priv->frag_thresh + 1; 92 wiphy->retry_short = priv->short_retry_limit; 93 wiphy->retry_long = priv->long_retry_limit; 94 95 return wiphy_register(wiphy); 96} 97 98static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev, 99 enum nl80211_iftype type, u32 *flags, 100 struct vif_params *params) 101{ 102 struct orinoco_private *priv = wiphy_priv(wiphy); 103 int err = 0; 104 unsigned long lock; 105 106 if (orinoco_lock(priv, &lock) != 0) 107 return -EBUSY; 108 109 switch (type) { 110 case NL80211_IFTYPE_ADHOC: 111 if (!priv->has_ibss && !priv->has_port3) 112 err = -EINVAL; 113 break; 114 115 case NL80211_IFTYPE_STATION: 116 break; 117 118 case NL80211_IFTYPE_MONITOR: 119 if (priv->broken_monitor && !force_monitor) { 120 wiphy_warn(wiphy, 121 "Monitor mode support is buggy in this firmware, not enabling\n"); 122 err = -EINVAL; 123 } 124 break; 125 126 default: 127 err = -EINVAL; 128 } 129 130 if (!err) { 131 priv->iw_mode = type; 132 set_port_type(priv); 133 err = orinoco_commit(priv); 134 } 135 136 orinoco_unlock(priv, &lock); 137 138 return err; 139} 140 141static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, 142 struct cfg80211_scan_request *request) 143{ 144 struct orinoco_private *priv = wiphy_priv(wiphy); 145 int err; 146 147 if (!request) 148 return -EINVAL; 149 150 if (priv->scan_request && priv->scan_request != request) 151 return -EBUSY; 152 153 priv->scan_request = request; 154 155 err = orinoco_hw_trigger_scan(priv, request->ssids); 156 157 return err; 158} 159 160static int orinoco_set_channel(struct wiphy *wiphy, 161 struct net_device *netdev, 162 struct ieee80211_channel *chan, 163 enum nl80211_channel_type channel_type) 164{ 165 struct orinoco_private *priv = wiphy_priv(wiphy); 166 int err = 0; 167 unsigned long flags; 168 int channel; 169 170 if (!chan) 171 return -EINVAL; 172 173 if (channel_type != NL80211_CHAN_NO_HT) 174 return -EINVAL; 175 176 if (chan->band != IEEE80211_BAND_2GHZ) 177 return -EINVAL; 178 179 channel = ieee80211_freq_to_dsss_chan(chan->center_freq); 180 181 if ((channel < 1) || (channel > NUM_CHANNELS) || 182 !(priv->channel_mask & (1 << (channel-1)))) 183 return -EINVAL; 184 185 if (orinoco_lock(priv, &flags) != 0) 186 return -EBUSY; 187 188 priv->channel = channel; 189 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { 190 /* Fast channel change - no commit if successful */ 191 hermes_t *hw = &priv->hw; 192 err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | 193 HERMES_TEST_SET_CHANNEL, 194 channel, NULL); 195 } 196 orinoco_unlock(priv, &flags); 197 198 return err; 199} 200 201static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) 202{ 203 struct orinoco_private *priv = wiphy_priv(wiphy); 204 int frag_value = -1; 205 int rts_value = -1; 206 int err = 0; 207 208 if (changed & WIPHY_PARAM_RETRY_SHORT) { 209 /* Setting short retry not supported */ 210 err = -EINVAL; 211 } 212 213 if (changed & WIPHY_PARAM_RETRY_LONG) { 214 /* Setting long retry not supported */ 215 err = -EINVAL; 216 } 217 218 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { 219 /* Set fragmentation */ 220 if (priv->has_mwo) { 221 if (wiphy->frag_threshold < 0) 222 frag_value = 0; 223 else { 224 printk(KERN_WARNING "%s: Fixed fragmentation " 225 "is not supported on this firmware. " 226 "Using MWO robust instead.\n", 227 priv->ndev->name); 228 frag_value = 1; 229 } 230 } else { 231 if (wiphy->frag_threshold < 0) 232 frag_value = 2346; 233 else if ((wiphy->frag_threshold < 257) || 234 (wiphy->frag_threshold > 2347)) 235 err = -EINVAL; 236 else 237 /* cfg80211 value is 257-2347 (odd only) 238 * orinoco rid has range 256-2346 (even only) */ 239 frag_value = wiphy->frag_threshold & ~0x1; 240 } 241 } 242 243 if (changed & WIPHY_PARAM_RTS_THRESHOLD) { 244 /* Set RTS. 245 * 246 * Prism documentation suggests default of 2432, 247 * and a range of 0-3000. 248 * 249 * Current implementation uses 2347 as the default and 250 * the upper limit. 251 */ 252 253 if (wiphy->rts_threshold < 0) 254 rts_value = 2347; 255 else if (wiphy->rts_threshold > 2347) 256 err = -EINVAL; 257 else 258 rts_value = wiphy->rts_threshold; 259 } 260 261 if (!err) { 262 unsigned long flags; 263 264 if (orinoco_lock(priv, &flags) != 0) 265 return -EBUSY; 266 267 if (frag_value >= 0) { 268 if (priv->has_mwo) 269 priv->mwo_robust = frag_value; 270 else 271 priv->frag_thresh = frag_value; 272 } 273 if (rts_value >= 0) 274 priv->rts_thresh = rts_value; 275 276 err = orinoco_commit(priv); 277 278 orinoco_unlock(priv, &flags); 279 } 280 281 return err; 282} 283 284const struct cfg80211_ops orinoco_cfg_ops = { 285 .change_virtual_intf = orinoco_change_vif, 286 .set_channel = orinoco_set_channel, 287 .scan = orinoco_scan, 288 .set_wiphy_params = orinoco_set_wiphy_params, 289}; 290