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 */ 14 static struct ieee80211_rate orinoco_rates[] = { 15 { .bitrate = 10 }, 16 { .bitrate = 20 }, 17 { .bitrate = 55 }, 18 { .bitrate = 110 }, 19 }; 20 21 static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid; 22 23 /* Called after orinoco_private is allocated. */ 24 void 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 */ 34 int 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_channel_to_frequency(i + 1, 63 NL80211_BAND_2GHZ); 64 channels++; 65 } 66 } 67 priv->band.channels = priv->channels; 68 priv->band.n_channels = channels; 69 70 wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; 71 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 72 73 i = 0; 74 if (priv->has_wep) { 75 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40; 76 i++; 77 78 if (priv->has_big_wep) { 79 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104; 80 i++; 81 } 82 } 83 if (priv->has_wpa) { 84 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP; 85 i++; 86 } 87 wiphy->cipher_suites = priv->cipher_suites; 88 wiphy->n_cipher_suites = i; 89 90 wiphy->rts_threshold = priv->rts_thresh; 91 if (!priv->has_mwo) 92 wiphy->frag_threshold = priv->frag_thresh + 1; 93 wiphy->retry_short = priv->short_retry_limit; 94 wiphy->retry_long = priv->long_retry_limit; 95 96 return wiphy_register(wiphy); 97 } 98 99 static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev, 100 enum nl80211_iftype type, u32 *flags, 101 struct vif_params *params) 102 { 103 struct orinoco_private *priv = wiphy_priv(wiphy); 104 int err = 0; 105 unsigned long lock; 106 107 if (orinoco_lock(priv, &lock) != 0) 108 return -EBUSY; 109 110 switch (type) { 111 case NL80211_IFTYPE_ADHOC: 112 if (!priv->has_ibss && !priv->has_port3) 113 err = -EINVAL; 114 break; 115 116 case NL80211_IFTYPE_STATION: 117 break; 118 119 case NL80211_IFTYPE_MONITOR: 120 if (priv->broken_monitor && !force_monitor) { 121 wiphy_warn(wiphy, 122 "Monitor mode support is buggy in this firmware, not enabling\n"); 123 err = -EINVAL; 124 } 125 break; 126 127 default: 128 err = -EINVAL; 129 } 130 131 if (!err) { 132 priv->iw_mode = type; 133 set_port_type(priv); 134 err = orinoco_commit(priv); 135 } 136 137 orinoco_unlock(priv, &lock); 138 139 return err; 140 } 141 142 static int orinoco_scan(struct wiphy *wiphy, 143 struct cfg80211_scan_request *request) 144 { 145 struct orinoco_private *priv = wiphy_priv(wiphy); 146 int err; 147 148 if (!request) 149 return -EINVAL; 150 151 if (priv->scan_request && priv->scan_request != request) 152 return -EBUSY; 153 154 priv->scan_request = request; 155 156 err = orinoco_hw_trigger_scan(priv, request->ssids); 157 /* On error the we aren't processing the request */ 158 if (err) 159 priv->scan_request = NULL; 160 161 return err; 162 } 163 164 static int orinoco_set_monitor_channel(struct wiphy *wiphy, 165 struct cfg80211_chan_def *chandef) 166 { 167 struct orinoco_private *priv = wiphy_priv(wiphy); 168 int err = 0; 169 unsigned long flags; 170 int channel; 171 172 if (!chandef->chan) 173 return -EINVAL; 174 175 if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT) 176 return -EINVAL; 177 178 if (chandef->chan->band != NL80211_BAND_2GHZ) 179 return -EINVAL; 180 181 channel = ieee80211_frequency_to_channel(chandef->chan->center_freq); 182 183 if ((channel < 1) || (channel > NUM_CHANNELS) || 184 !(priv->channel_mask & (1 << (channel - 1)))) 185 return -EINVAL; 186 187 if (orinoco_lock(priv, &flags) != 0) 188 return -EBUSY; 189 190 priv->channel = channel; 191 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { 192 /* Fast channel change - no commit if successful */ 193 struct hermes *hw = &priv->hw; 194 err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST | 195 HERMES_TEST_SET_CHANNEL, 196 channel, NULL); 197 } 198 orinoco_unlock(priv, &flags); 199 200 return err; 201 } 202 203 static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) 204 { 205 struct orinoco_private *priv = wiphy_priv(wiphy); 206 int frag_value = -1; 207 int rts_value = -1; 208 int err = 0; 209 210 if (changed & WIPHY_PARAM_RETRY_SHORT) { 211 /* Setting short retry not supported */ 212 err = -EINVAL; 213 } 214 215 if (changed & WIPHY_PARAM_RETRY_LONG) { 216 /* Setting long retry not supported */ 217 err = -EINVAL; 218 } 219 220 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { 221 /* Set fragmentation */ 222 if (priv->has_mwo) { 223 if (wiphy->frag_threshold == -1) 224 frag_value = 0; 225 else { 226 printk(KERN_WARNING "%s: Fixed fragmentation " 227 "is not supported on this firmware. " 228 "Using MWO robust instead.\n", 229 priv->ndev->name); 230 frag_value = 1; 231 } 232 } else { 233 if (wiphy->frag_threshold == -1) 234 frag_value = 2346; 235 else if ((wiphy->frag_threshold < 257) || 236 (wiphy->frag_threshold > 2347)) 237 err = -EINVAL; 238 else 239 /* cfg80211 value is 257-2347 (odd only) 240 * orinoco rid has range 256-2346 (even only) */ 241 frag_value = wiphy->frag_threshold & ~0x1; 242 } 243 } 244 245 if (changed & WIPHY_PARAM_RTS_THRESHOLD) { 246 /* Set RTS. 247 * 248 * Prism documentation suggests default of 2432, 249 * and a range of 0-3000. 250 * 251 * Current implementation uses 2347 as the default and 252 * the upper limit. 253 */ 254 255 if (wiphy->rts_threshold == -1) 256 rts_value = 2347; 257 else if (wiphy->rts_threshold > 2347) 258 err = -EINVAL; 259 else 260 rts_value = wiphy->rts_threshold; 261 } 262 263 if (!err) { 264 unsigned long flags; 265 266 if (orinoco_lock(priv, &flags) != 0) 267 return -EBUSY; 268 269 if (frag_value >= 0) { 270 if (priv->has_mwo) 271 priv->mwo_robust = frag_value; 272 else 273 priv->frag_thresh = frag_value; 274 } 275 if (rts_value >= 0) 276 priv->rts_thresh = rts_value; 277 278 err = orinoco_commit(priv); 279 280 orinoco_unlock(priv, &flags); 281 } 282 283 return err; 284 } 285 286 const struct cfg80211_ops orinoco_cfg_ops = { 287 .change_virtual_intf = orinoco_change_vif, 288 .set_monitor_channel = orinoco_set_monitor_channel, 289 .scan = orinoco_scan, 290 .set_wiphy_params = orinoco_set_wiphy_params, 291 }; 292