0001
0002
0003
0004
0005 #include <linux/ieee80211.h>
0006 #include <net/cfg80211.h>
0007 #include "hw.h"
0008 #include "main.h"
0009 #include "orinoco.h"
0010
0011 #include "cfg.h"
0012
0013
0014 static struct ieee80211_rate orinoco_rates[] = {
0015 { .bitrate = 10 },
0016 { .bitrate = 20 },
0017 { .bitrate = 55 },
0018 { .bitrate = 110 },
0019 };
0020
0021 static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
0022
0023
0024 void orinoco_wiphy_init(struct wiphy *wiphy)
0025 {
0026 struct orinoco_private *priv = wiphy_priv(wiphy);
0027
0028 wiphy->privid = orinoco_wiphy_privid;
0029
0030 set_wiphy_dev(wiphy, priv->dev);
0031 }
0032
0033
0034 int orinoco_wiphy_register(struct wiphy *wiphy)
0035 {
0036 struct orinoco_private *priv = wiphy_priv(wiphy);
0037 int i, channels = 0;
0038
0039 if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
0040 wiphy->max_scan_ssids = 1;
0041 else
0042 wiphy->max_scan_ssids = 0;
0043
0044 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
0045
0046
0047
0048
0049 if (priv->has_ibss)
0050 wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
0051
0052 if (!priv->broken_monitor || force_monitor)
0053 wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
0054
0055 priv->band.bitrates = orinoco_rates;
0056 priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);
0057
0058
0059 for (i = 0; i < NUM_CHANNELS; i++) {
0060 if (priv->channel_mask & (1 << i)) {
0061 priv->channels[i].center_freq =
0062 ieee80211_channel_to_frequency(i + 1,
0063 NL80211_BAND_2GHZ);
0064 channels++;
0065 }
0066 }
0067 priv->band.channels = priv->channels;
0068 priv->band.n_channels = channels;
0069
0070 wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
0071 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
0072
0073 i = 0;
0074 if (priv->has_wep) {
0075 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
0076 i++;
0077
0078 if (priv->has_big_wep) {
0079 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
0080 i++;
0081 }
0082 }
0083 if (priv->has_wpa) {
0084 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
0085 i++;
0086 }
0087 wiphy->cipher_suites = priv->cipher_suites;
0088 wiphy->n_cipher_suites = i;
0089
0090 wiphy->rts_threshold = priv->rts_thresh;
0091 if (!priv->has_mwo)
0092 wiphy->frag_threshold = priv->frag_thresh + 1;
0093 wiphy->retry_short = priv->short_retry_limit;
0094 wiphy->retry_long = priv->long_retry_limit;
0095
0096 return wiphy_register(wiphy);
0097 }
0098
0099 static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
0100 enum nl80211_iftype type,
0101 struct vif_params *params)
0102 {
0103 struct orinoco_private *priv = wiphy_priv(wiphy);
0104 int err = 0;
0105 unsigned long lock;
0106
0107 if (orinoco_lock(priv, &lock) != 0)
0108 return -EBUSY;
0109
0110 switch (type) {
0111 case NL80211_IFTYPE_ADHOC:
0112 if (!priv->has_ibss && !priv->has_port3)
0113 err = -EINVAL;
0114 break;
0115
0116 case NL80211_IFTYPE_STATION:
0117 break;
0118
0119 case NL80211_IFTYPE_MONITOR:
0120 if (priv->broken_monitor && !force_monitor) {
0121 wiphy_warn(wiphy,
0122 "Monitor mode support is buggy in this firmware, not enabling\n");
0123 err = -EINVAL;
0124 }
0125 break;
0126
0127 default:
0128 err = -EINVAL;
0129 }
0130
0131 if (!err) {
0132 priv->iw_mode = type;
0133 set_port_type(priv);
0134 err = orinoco_commit(priv);
0135 }
0136
0137 orinoco_unlock(priv, &lock);
0138
0139 return err;
0140 }
0141
0142 static int orinoco_scan(struct wiphy *wiphy,
0143 struct cfg80211_scan_request *request)
0144 {
0145 struct orinoco_private *priv = wiphy_priv(wiphy);
0146 int err;
0147
0148 if (!request)
0149 return -EINVAL;
0150
0151 if (priv->scan_request && priv->scan_request != request)
0152 return -EBUSY;
0153
0154 priv->scan_request = request;
0155
0156 err = orinoco_hw_trigger_scan(priv, request->ssids);
0157
0158 if (err)
0159 priv->scan_request = NULL;
0160
0161 return err;
0162 }
0163
0164 static int orinoco_set_monitor_channel(struct wiphy *wiphy,
0165 struct cfg80211_chan_def *chandef)
0166 {
0167 struct orinoco_private *priv = wiphy_priv(wiphy);
0168 int err = 0;
0169 unsigned long flags;
0170 int channel;
0171
0172 if (!chandef->chan)
0173 return -EINVAL;
0174
0175 if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
0176 return -EINVAL;
0177
0178 if (chandef->chan->band != NL80211_BAND_2GHZ)
0179 return -EINVAL;
0180
0181 channel = ieee80211_frequency_to_channel(chandef->chan->center_freq);
0182
0183 if ((channel < 1) || (channel > NUM_CHANNELS) ||
0184 !(priv->channel_mask & (1 << (channel - 1))))
0185 return -EINVAL;
0186
0187 if (orinoco_lock(priv, &flags) != 0)
0188 return -EBUSY;
0189
0190 priv->channel = channel;
0191 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
0192
0193 struct hermes *hw = &priv->hw;
0194 err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
0195 HERMES_TEST_SET_CHANNEL,
0196 channel, NULL);
0197 }
0198 orinoco_unlock(priv, &flags);
0199
0200 return err;
0201 }
0202
0203 static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
0204 {
0205 struct orinoco_private *priv = wiphy_priv(wiphy);
0206 int frag_value = -1;
0207 int rts_value = -1;
0208 int err = 0;
0209
0210 if (changed & WIPHY_PARAM_RETRY_SHORT) {
0211
0212 err = -EINVAL;
0213 }
0214
0215 if (changed & WIPHY_PARAM_RETRY_LONG) {
0216
0217 err = -EINVAL;
0218 }
0219
0220 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
0221
0222 if (priv->has_mwo) {
0223 if (wiphy->frag_threshold == -1)
0224 frag_value = 0;
0225 else {
0226 printk(KERN_WARNING "%s: Fixed fragmentation "
0227 "is not supported on this firmware. "
0228 "Using MWO robust instead.\n",
0229 priv->ndev->name);
0230 frag_value = 1;
0231 }
0232 } else {
0233 if (wiphy->frag_threshold == -1)
0234 frag_value = 2346;
0235 else if ((wiphy->frag_threshold < 257) ||
0236 (wiphy->frag_threshold > 2347))
0237 err = -EINVAL;
0238 else
0239
0240
0241 frag_value = wiphy->frag_threshold & ~0x1;
0242 }
0243 }
0244
0245 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 if (wiphy->rts_threshold == -1)
0256 rts_value = 2347;
0257 else if (wiphy->rts_threshold > 2347)
0258 err = -EINVAL;
0259 else
0260 rts_value = wiphy->rts_threshold;
0261 }
0262
0263 if (!err) {
0264 unsigned long flags;
0265
0266 if (orinoco_lock(priv, &flags) != 0)
0267 return -EBUSY;
0268
0269 if (frag_value >= 0) {
0270 if (priv->has_mwo)
0271 priv->mwo_robust = frag_value;
0272 else
0273 priv->frag_thresh = frag_value;
0274 }
0275 if (rts_value >= 0)
0276 priv->rts_thresh = rts_value;
0277
0278 err = orinoco_commit(priv);
0279
0280 orinoco_unlock(priv, &flags);
0281 }
0282
0283 return err;
0284 }
0285
0286 const struct cfg80211_ops orinoco_cfg_ops = {
0287 .change_virtual_intf = orinoco_change_vif,
0288 .set_monitor_channel = orinoco_set_monitor_channel,
0289 .scan = orinoco_scan,
0290 .set_wiphy_params = orinoco_set_wiphy_params,
0291 };