@@ -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;
@@ -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;
@@ -669,7 +669,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;
@@ -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);
@@ -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;
@@ -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;
@@ -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;
}
@@ -483,7 +483,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;
@@ -536,7 +536,14 @@ 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;
@@ -550,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;
@@ -567,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
@@ -590,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[] = {
@@ -630,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;
@@ -642,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;
@@ -659,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) {
@@ -673,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;
}
@@ -684,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. */
@@ -700,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) {
@@ -732,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,