diff options
Diffstat (limited to 'package/mac80211/patches/015-hostapd-ioctl-hw-features.patch')
-rw-r--r-- | package/mac80211/patches/015-hostapd-ioctl-hw-features.patch | 122 |
1 files changed, 122 insertions, 0 deletions
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 index 0000000..d6e5dfd --- /dev/null +++ b/package/mac80211/patches/015-hostapd-ioctl-hw-features.patch @@ -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; |