|
@@ -8,6 +8,7 @@
|
|
|
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/if_arp.h>
|
|
|
+#include <linux/ieee80211.h>
|
|
|
#include <net/cfg80211.h>
|
|
|
#include <asm/unaligned.h>
|
|
|
|
|
@@ -2042,6 +2043,7 @@ int lbs_cfg_register(struct lbs_private *priv)
|
|
|
*/
|
|
|
wdev->wiphy->cipher_suites = cipher_suites;
|
|
|
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
|
|
|
+ wdev->wiphy->reg_notifier = lbs_reg_notifier;
|
|
|
|
|
|
ret = wiphy_register(wdev->wiphy);
|
|
|
if (ret < 0)
|
|
@@ -2061,6 +2063,114 @@ int lbs_cfg_register(struct lbs_private *priv)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @brief This function sets DOMAIN INFO to FW
|
|
|
+ * @param priv pointer to struct lbs_private
|
|
|
+ * @return 0; -1
|
|
|
+*/
|
|
|
+static int lbs_11d_set_domain_info(struct lbs_private *priv)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
|
|
|
+ CMD_ACT_SET,
|
|
|
+ CMD_OPTION_WAITFORRSP, 0, NULL);
|
|
|
+ if (ret)
|
|
|
+ lbs_deb_11d("fail to dnld domain info\n");
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void lbs_send_domain_info_cmd_fw(struct wiphy *wiphy,
|
|
|
+ struct regulatory_request *request)
|
|
|
+{
|
|
|
+ u8 no_of_triplet = 0;
|
|
|
+ u8 no_of_parsed_chan = 0;
|
|
|
+ u8 first_channel = 0, next_chan = 0, max_pwr = 0;
|
|
|
+ u8 i, flag = 0;
|
|
|
+ enum ieee80211_band band;
|
|
|
+ struct ieee80211_supported_band *sband;
|
|
|
+ struct ieee80211_channel *ch;
|
|
|
+ struct lbs_private *priv = wiphy_priv(wiphy);
|
|
|
+ struct lbs_802_11d_domain_reg *domain_info = &priv->domain_reg;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ lbs_deb_enter(LBS_DEB_CFG80211);
|
|
|
+
|
|
|
+ /* Set country code */
|
|
|
+ domain_info->country_code[0] = request->alpha2[0];
|
|
|
+ domain_info->country_code[1] = request->alpha2[1];
|
|
|
+ domain_info->country_code[2] = ' ';
|
|
|
+
|
|
|
+ for (band = 0; band < IEEE80211_NUM_BANDS ; band++) {
|
|
|
+
|
|
|
+ if (!wiphy->bands[band])
|
|
|
+ continue;
|
|
|
+
|
|
|
+ sband = wiphy->bands[band];
|
|
|
+
|
|
|
+ for (i = 0; i < sband->n_channels ; i++) {
|
|
|
+ ch = &sband->channels[i];
|
|
|
+ if (ch->flags & IEEE80211_CHAN_DISABLED)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (!flag) {
|
|
|
+ flag = 1;
|
|
|
+ next_chan = first_channel = (u32) ch->hw_value;
|
|
|
+ max_pwr = ch->max_power;
|
|
|
+ no_of_parsed_chan = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ch->hw_value == next_chan + 1 &&
|
|
|
+ ch->max_power == max_pwr) {
|
|
|
+ next_chan++;
|
|
|
+ no_of_parsed_chan++;
|
|
|
+ } else {
|
|
|
+ domain_info->triplet[no_of_triplet]
|
|
|
+ .chans.first_channel = first_channel;
|
|
|
+ domain_info->triplet[no_of_triplet]
|
|
|
+ .chans.num_channels = no_of_parsed_chan;
|
|
|
+ domain_info->triplet[no_of_triplet]
|
|
|
+ .chans.max_power = max_pwr;
|
|
|
+ no_of_triplet++;
|
|
|
+ flag = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (flag) {
|
|
|
+ domain_info->triplet[no_of_triplet]
|
|
|
+ .chans.first_channel = first_channel;
|
|
|
+ domain_info->triplet[no_of_triplet]
|
|
|
+ .chans.num_channels = no_of_parsed_chan;
|
|
|
+ domain_info->triplet[no_of_triplet]
|
|
|
+ .chans.max_power = max_pwr;
|
|
|
+ no_of_triplet++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ domain_info->no_triplet = no_of_triplet;
|
|
|
+
|
|
|
+ /* Set domain info */
|
|
|
+ ret = lbs_11d_set_domain_info(priv);
|
|
|
+ if (ret)
|
|
|
+ lbs_pr_err("11D: error setting domain info in FW\n");
|
|
|
+
|
|
|
+ lbs_deb_leave(LBS_DEB_CFG80211);
|
|
|
+}
|
|
|
+
|
|
|
+int lbs_reg_notifier(struct wiphy *wiphy,
|
|
|
+ struct regulatory_request *request)
|
|
|
+{
|
|
|
+ lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
|
|
|
+ "callback for domain %c%c\n", request->alpha2[0],
|
|
|
+ request->alpha2[1]);
|
|
|
+
|
|
|
+ lbs_send_domain_info_cmd_fw(wiphy, request);
|
|
|
+
|
|
|
+ lbs_deb_leave(LBS_DEB_CFG80211);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
void lbs_scan_deinit(struct lbs_private *priv)
|
|
|
{
|