fix up hostapd for mac80211
[openwrt/openwrt.git] / package / mac80211 / patches / 015-hostapd-ioctl-hw-features.patch
diff --git a/package/mac80211/patches/015-hostapd-ioctl-hw-features.patch b/package/mac80211/patches/015-hostapd-ioctl-hw-features.patch
new file mode 100644 (file)
index 0000000..d6e5dfd
--- /dev/null
@@ -0,0 +1,122 @@
+---
+ net/mac80211/ieee80211_ioctl.c |  102 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 102 insertions(+)
+
+--- everything.orig/net/mac80211/ieee80211_ioctl.c     2007-11-07 13:19:32.281514919 +0100
++++ everything/net/mac80211/ieee80211_ioctl.c  2007-11-07 13:19:33.681513453 +0100
+@@ -125,6 +125,105 @@ static int ieee80211_ioctl_siwgenie(stru
+       return -EOPNOTSUPP;
+ }
++/*
++ * Wow. This ioctl interface is such crap, it's tied
++ * to internal definitions. I hope it dies soon.
++ */
++static int mode_to_hostapd_mode(enum ieee80211_phymode mode)
++{
++      switch (mode) {
++      case MODE_IEEE80211A:
++              return 0;
++      case MODE_IEEE80211B:
++              return 1;
++      case MODE_IEEE80211G:
++              return 3;
++      case NUM_IEEE80211_MODES:
++              WARN_ON(1);
++              break;
++      }
++      WARN_ON(1);
++      return -1;
++}
++
++static int channel_flags_to_hostapd_flags(int flags)
++{
++      int res = 0;
++
++      if (flags & IEEE80211_CHAN_W_SCAN)
++              res |= 1;
++      if (flags & IEEE80211_CHAN_W_ACTIVE_SCAN)
++              res |= 2;
++      if (flags & IEEE80211_CHAN_W_IBSS)
++              res |= 4;
++
++      return res;
++}
++
++struct ieee80211_channel_data {
++      short chan; /* channel number (IEEE 802.11) */
++      short freq; /* frequency in MHz */
++      int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
++};
++
++struct ieee80211_rate_data {
++      int rate; /* rate in 100 kbps */
++      int flags; /* IEEE80211_RATE_ flags */
++};
++
++static int ieee80211_ioctl_get_hw_features(struct net_device *dev,
++                                         struct prism2_hostapd_param *param,
++                                         int param_len)
++{
++      struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++      u8 *pos = param->u.hw_features.data;
++      int left = param_len - (pos - (u8 *) param);
++      int i;
++      struct hostapd_ioctl_hw_modes_hdr *hdr;
++      struct ieee80211_rate_data *rate;
++      struct ieee80211_channel_data *chan;
++      struct ieee80211_hw_mode *mode;
++
++      param->u.hw_features.flags = 0;
++
++      param->u.hw_features.num_modes = 0;
++      list_for_each_entry(mode, &local->modes_list, list) {
++              int clen, rlen;
++
++              param->u.hw_features.num_modes++;
++              clen =
++                  mode->num_channels * sizeof(struct ieee80211_channel_data);
++              rlen = mode->num_rates * sizeof(struct ieee80211_rate_data);
++              if (left < sizeof(*hdr) + clen + rlen)
++                      return -E2BIG;
++              left -= sizeof(*hdr) + clen + rlen;
++
++              hdr = (struct hostapd_ioctl_hw_modes_hdr *)pos;
++              hdr->mode = mode_to_hostapd_mode(mode->mode);
++              hdr->num_channels = mode->num_channels;
++              hdr->num_rates = mode->num_rates;
++
++              pos = (u8 *) (hdr + 1);
++              chan = (struct ieee80211_channel_data *)pos;
++              for (i = 0; i < mode->num_channels; i++) {
++                      chan[i].chan = mode->channels[i].chan;
++                      chan[i].freq = mode->channels[i].freq;
++                      chan[i].flag = channel_flags_to_hostapd_flags(
++                                              mode->channels[i].flag);
++              }
++              pos += clen;
++
++              rate = (struct ieee80211_rate_data *)pos;
++              for (i = 0; i < mode->num_rates; i++) {
++                      rate[i].rate = mode->rates[i].rate;
++                      rate[i].flags = mode->rates[i].flags;
++              }
++              pos += rlen;
++      }
++
++      return 0;
++}
++
+ static int ieee80211_ioctl_priv_hostapd(struct net_device *dev,
+                                       struct iw_point *p)
+@@ -151,6 +250,9 @@ static int ieee80211_ioctl_priv_hostapd(
+       }
+       switch (param->cmd) {
++      case PRISM2_HOSTAPD_GET_HW_FEATURES:
++              ret = ieee80211_ioctl_get_hw_features(dev, param, p->length);
++              break;
+       default:
+               ret = -EOPNOTSUPP;
+               break;