]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: S1G: add frequency set in kHz and offset options
authorGilad Itzkovitch <gilad.itzkovitch@morsemicro.com>
Mon, 27 Feb 2023 02:05:29 +0000 (15:05 +1300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 14 Apr 2023 11:01:26 +0000 (13:01 +0200)
This change adds support to specify the set frequency in kHz for
the set frequency command which include an offset whenever needed.
Also, it adds S1G bandwidth options to the selected chandef.

Signed-off-by: Gilad Itzkovitch <gilad.itzkovitch@morsemicro.com>
Link: https://lore.kernel.org/r/20230227020529.504934-1-gilad.itzkovitch@virscient.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
ap.c
ibss.c
interface.c
iw.h
mesh.c
ocb.c
phy.c
util.c

diff --git a/ap.c b/ap.c
index db9efb7b47ff1976a2f35ff88828b718dc729d24..748576d512b8df89921c3a49ac0cde52890d776d 100644 (file)
--- a/ap.c
+++ b/ap.c
@@ -28,7 +28,7 @@ static int handle_start_ap(struct nl80211_state *state,
        argc--;
 
        /* chandef */
-       res = parse_freqchan(&chandef, false, argc, argv, &parsed);
+       res = parse_freqchan(&chandef, false, argc, argv, &parsed, false);
        if (res)
                return res;
        argc -= parsed;
diff --git a/ibss.c b/ibss.c
index f6cbc4ca88017ecdbcf3df60bcd0e335ebddba57..6e6a835d76b93bbd40d29fa64984ea9bf4b27a5a 100644 (file)
--- a/ibss.c
+++ b/ibss.c
@@ -30,7 +30,7 @@ static int join_ibss(struct nl80211_state *state,
        argv++;
        argc--;
 
-       err = parse_freqchan(&chandef, false, argc, argv, &parsed);
+       err = parse_freqchan(&chandef, false, argc, argv, &parsed, false);
        if (err)
                return err;
 
index 7e1dd58c68eff098aa55eec994f0493f2ed44417..eeef496c4956eaaaebe48946dc867efe652547cc 100644 (file)
@@ -701,7 +701,7 @@ static int handle_chanfreq(struct nl80211_state *state, struct nl_msg *msg,
        int parsed;
        char *end;
 
-       res = parse_freqchan(&chandef, chan, argc, argv, &parsed);
+       res = parse_freqchan(&chandef, chan, argc, argv, &parsed, false);
        if (res)
                return res;
 
diff --git a/iw.h b/iw.h
index 45e4fbee8a7b5fb4113b354c302bc37257b86af5..19c76cf0a4b69e15b91db902904aacd413d5fa2f 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -102,7 +102,9 @@ struct chandef {
        enum nl80211_chan_width width;
 
        unsigned int control_freq;
+       unsigned int control_freq_offset;
        unsigned int center_freq1;
+       unsigned int center_freq1_offset;
        unsigned int center_freq2;
 };
 
@@ -207,7 +209,8 @@ int parse_hex_mask(char *hexmask, unsigned char **result, size_t *result_len,
 unsigned char *parse_hex(char *hex, size_t *outlen);
 
 int parse_keys(struct nl_msg *msg, char **argv[], int *argc);
-int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv, int *parsed);
+int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
+                   int *parsed, bool freq_in_khz);
 enum nl80211_chan_width str_to_bw(const char *str);
 int parse_txq_stats(char *buf, int buflen, struct nlattr *tid_stats_attr, int header,
                    int tid, const char *indent);
diff --git a/mesh.c b/mesh.c
index 0fb98a3030ed5264c06e1f9f7a25a2d7523542ab..40e5e5e8f0da1dbc2f5b8a1a512fba7a342d7b84 100644 (file)
--- a/mesh.c
+++ b/mesh.c
@@ -485,7 +485,7 @@ static int join_mesh(struct nl80211_state *state,
                int err, parsed;
 
                err = parse_freqchan(&chandef, false, argc - 1, argv + 1,
-                                    &parsed);
+                                    &parsed, false);
                if (err)
                        return err;
 
diff --git a/ocb.c b/ocb.c
index fc9579b8f3d0603bb0c003ec69395e32360b9089..ee0eedf2c663bbeecaefa95c3ef8d5feb043f267 100644 (file)
--- a/ocb.c
+++ b/ocb.c
@@ -16,7 +16,7 @@ static int join_ocb(struct nl80211_state *state,
        if (argc < 2)
                return 1;
 
-       err = parse_freqchan(&chandef, false, argc, argv, &parsed);
+       err = parse_freqchan(&chandef, false, argc, argv, &parsed, false);
 
        if (err)
                return err;
diff --git a/phy.c b/phy.c
index 15cea32321bff757ba0a74d0b2830c982111887f..472212571858ee16c9fb5ad1a393a2f4849ed900 100644 (file)
--- a/phy.c
+++ b/phy.c
@@ -191,7 +191,7 @@ static int handle_freq(struct nl80211_state *state, struct nl_msg *msg,
        struct chandef chandef;
        int res;
 
-       res = parse_freqchan(&chandef, false, argc, argv, NULL);
+       res = parse_freqchan(&chandef, false, argc, argv, NULL, false);
        if (res)
                return res;
 
@@ -209,6 +209,31 @@ COMMAND(set, freq,
        "<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
        NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
 
+static int handle_freq_khz(struct nl80211_state *state, struct nl_msg *msg,
+                      int argc, char **argv,
+                      enum id_input id)
+{
+       struct chandef chandef;
+       int res;
+
+       res = parse_freqchan(&chandef, false, argc, argv, NULL, true);
+       if (res)
+               return res;
+
+       return put_chandef(msg, &chandef);
+}
+
+COMMAND(set, freq_khz,
+       "<freq> [1MHz|2MHz|4MHz|8MHz|16MHz]\n"
+       "<control freq> [1|2|4|8|16] [<center1_freq> [<center2_freq>]]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq_khz,
+       "Set frequency in kHz the hardware is using\n"
+       "configuration.");
+COMMAND(set, freq_khz,
+       "<freq> [1MHz|2MHz|4MHz|8MHz|16MHz]\n"
+       "<control freq> [1|2|4|8|16] [<center1_freq> [<center2_freq>]]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq_khz, NULL);
+
 static int handle_chan(struct nl80211_state *state, struct nl_msg *msg,
                       int argc, char **argv,
                       enum id_input id)
@@ -216,7 +241,7 @@ static int handle_chan(struct nl80211_state *state, struct nl_msg *msg,
        struct chandef chandef;
        int res;
 
-       res = parse_freqchan(&chandef, true, argc, argv, NULL);
+       res = parse_freqchan(&chandef, true, argc, argv, NULL, false);
        if (res)
                return res;
 
@@ -288,9 +313,9 @@ static int handle_cac_trigger(struct nl80211_state *state,
                return 1;
 
        if (strcmp(argv[0], "channel") == 0) {
-               res = parse_freqchan(&chandef, true, argc - 1, argv + 1, NULL);
+               res = parse_freqchan(&chandef, true, argc - 1, argv + 1, NULL, false);
        } else if (strcmp(argv[0], "freq") == 0) {
-               res = parse_freqchan(&chandef, false, argc - 1, argv + 1, NULL);
+               res = parse_freqchan(&chandef, false, argc - 1, argv + 1, NULL, false);
        } else {
                return 1;
        }
@@ -334,9 +359,9 @@ static int handle_cac(struct nl80211_state *state,
                return 1;
 
        if (strcmp(argv[2], "channel") == 0) {
-               err = parse_freqchan(&chandef, true, argc - 3, argv + 3, NULL);
+               err = parse_freqchan(&chandef, true, argc - 3, argv + 3, NULL, false);
        } else if (strcmp(argv[2], "freq") == 0) {
-               err = parse_freqchan(&chandef, false, argc - 3, argv + 3, NULL);
+               err = parse_freqchan(&chandef, false, argc - 3, argv + 3, NULL, false);
        } else {
                err = 1;
        }
diff --git a/util.c b/util.c
index 50e3fbc41f82aa690e217976d900c255ac355b20..eef0332b2a2faa4208f49e1c6776f372080234e6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -484,7 +484,7 @@ enum nl80211_chan_width str_to_bw(const char *str)
 }
 
 static int parse_freqs(struct chandef *chandef, int argc, char **argv,
-                      int *parsed)
+                      int *parsed, bool freq_in_khz)
 {
        uint32_t freq;
        char *end;
@@ -537,7 +537,13 @@ static int parse_freqs(struct chandef *chandef, int argc, char **argv,
                return 1;
        *parsed += 1;
 
-       chandef->center_freq1 = freq;
+       if (freq_in_khz) {
+               chandef->center_freq1 = freq / 1000;
+               chandef->center_freq1_offset = freq % 1000;
+       } else {
+               chandef->center_freq1 = freq;
+               chandef->center_freq1_offset = 0;
+       }
 
        if (!need_cf2)
                return 0;
@@ -551,7 +557,11 @@ static int parse_freqs(struct chandef *chandef, int argc, char **argv,
        freq = strtoul(argv[2], &end, 10);
        if (*end)
                return 1;
-       chandef->center_freq2 = freq;
+
+       if (freq_in_khz)
+               chandef->center_freq2 = freq / 1000;
+       else
+               chandef->center_freq2 = freq;
 
        *parsed += 1;
 
@@ -568,6 +578,7 @@ static int parse_freqs(struct chandef *chandef, int argc, char **argv,
  * @argv: Array of string arguments
  * @parsed: Pointer to return the number of used arguments, or NULL to error
  *          out if any argument is left unused.
+ * @freq_in_khz: Boolean whether to parse the frequency in kHz or default as MHz
  *
  * The given chandef structure will be filled in from the command line
  * arguments. argc/argv will be updated so that further arguments from the
@@ -591,7 +602,7 @@ static int parse_freqs(struct chandef *chandef, int argc, char **argv,
  * Return: Number of used arguments, zero or negative error number otherwise
  */
 int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
-                  int *parsed)
+                  int *parsed, bool freq_in_khz)
 {
        char *end;
        static const struct chanmode chanmode[] = {
@@ -631,9 +642,30 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
                  .width = NL80211_CHAN_WIDTH_320,
                  .freq1_diff = 0,
                  .chantype = -1 },
+               { .name = "1MHz",
+                 .width = NL80211_CHAN_WIDTH_1,
+                 .freq1_diff = 0,
+                 .chantype = -1 },
+               { .name = "2MHz",
+                 .width = NL80211_CHAN_WIDTH_2,
+                 .freq1_diff = 0,
+                 .chantype = -1 },
+               { .name = "4MHz",
+                 .width = NL80211_CHAN_WIDTH_4,
+                 .freq1_diff = 0,
+                 .chantype = -1 },
+               { .name = "8MHz",
+                 .width = NL80211_CHAN_WIDTH_8,
+                 .freq1_diff = 0,
+                 .chantype = -1 },
+               { .name = "16MHz",
+                 .width = NL80211_CHAN_WIDTH_16,
+                 .freq1_diff = 0,
+                 .chantype = -1 },
+
        };
        const struct chanmode *chanmode_selected = NULL;
-       unsigned int freq;
+       unsigned int freq, freq_offset = 0;
        unsigned int i;
        int _parsed = 0;
        int res = 0;
@@ -643,7 +675,14 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
 
        if (!argv[0])
                goto out;
+
        freq = strtoul(argv[0], &end, 10);
+
+       if (freq_in_khz) {
+               freq_offset = freq % 1000;
+               freq = freq / 1000;
+       }
+
        if (*end) {
                res = 1;
                goto out;
@@ -660,8 +699,10 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
                freq = ieee80211_channel_to_frequency(freq, band);
        }
        chandef->control_freq = freq;
+       chandef->control_freq_offset = freq_offset;
        /* Assume 20MHz NOHT channel for now. */
        chandef->center_freq1 = freq;
+       chandef->center_freq1_offset = freq_offset;
 
        /* Try to parse HT mode definitions */
        if (argc > 1) {
@@ -674,9 +715,20 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
                }
        }
 
+       /* Set channel width's default value */
+       if (chandef->control_freq < 1000)
+               chandef->width = NL80211_CHAN_WIDTH_16;
+       else
+               chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+
        /* channel mode given, use it and return. */
        if (chanmode_selected) {
                chandef->center_freq1 = get_cf1(chanmode_selected, freq);
+
+               /* For non-S1G frequency */
+               if (chandef->center_freq1 > 1000)
+                       chandef->center_freq1_offset = 0;
+
                chandef->width = chanmode_selected->width;
                goto out;
        }
@@ -685,7 +737,7 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
        if (chan)
                goto out;
 
-       res = parse_freqs(chandef, argc - 1, argv + 1, &_parsed);
+       res = parse_freqs(chandef, argc - 1, argv + 1, &_parsed, freq_in_khz);
 
  out:
        /* Error out if parsed is NULL. */
@@ -701,6 +753,9 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
 int put_chandef(struct nl_msg *msg, struct chandef *chandef)
 {
        NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chandef->control_freq);
+       NLA_PUT_U32(msg,
+                   NL80211_ATTR_WIPHY_FREQ_OFFSET,
+                   chandef->control_freq_offset);
        NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width);
 
        switch (chandef->width) {
@@ -733,6 +788,11 @@ int put_chandef(struct nl_msg *msg, struct chandef *chandef)
                            NL80211_ATTR_CENTER_FREQ1,
                            chandef->center_freq1);
 
+       if (chandef->center_freq1_offset)
+               NLA_PUT_U32(msg,
+                           NL80211_ATTR_CENTER_FREQ1_OFFSET,
+                           chandef->center_freq1_offset);
+
        if (chandef->center_freq2)
                NLA_PUT_U32(msg,
                            NL80211_ATTR_CENTER_FREQ2,