iw: Add support for specifying the 160MHz bandwidth when setting the channel/frequency

The current iw tool only supports the direct setting of
[NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] bandwidth
when setting the channel/frequency.

If we want to set the 160MHz bandwidth,
we need to calculate the center frequency ourselves,
which is inconvenient.

E.g:
iw phy phy0 set freq 5220 160 5250

From now on we can:
iw phy phy0 set channel 44 160MHz
iw phy phy0 set freq 5220 160MHz

This is much more convenient.

Signed-off-by: AK Deng <ttttabcd@protonmail.com>
Link: https://lore.kernel.org/r/cIf-30s-5axo5iDqyzwY9VTVB_JLKCXbxlXdODMSK61q-yFzR6rtAk8URRAPavRlllrwXr1Q-jtem_upoCNKd_fba8qmM0DpJn0O7MIkq6o=@protonmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
diff --git a/phy.c b/phy.c
index 716677e..2d489ef 100644
--- a/phy.c
+++ b/phy.c
@@ -199,13 +199,13 @@
 }
 
 COMMAND(set, freq,
-	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]\n"
 	"<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
 	"Set frequency/channel the hardware is using, including HT\n"
 	"configuration.");
 COMMAND(set, freq,
-	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]\n"
 	"<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
 
@@ -222,9 +222,9 @@
 
 	return put_chandef(msg, &chandef);
 }
-COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
+COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
-COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
+COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
 
 
diff --git a/util.c b/util.c
index 186e05b..0a9083c 100644
--- a/util.c
+++ b/util.c
@@ -576,10 +576,10 @@
  * user by giving "NOHT" instead.
  *
  * The working specifier if chan is set are:
- *   <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]
+ *   <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]
  *
  * And if frequency is set:
- *   <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]
+ *   <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]
  *   <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]
  *
  * If the mode/channel width is not given the NOHT is assumed.
@@ -619,6 +619,10 @@
 		  .width = NL80211_CHAN_WIDTH_80,
 		  .freq1_diff = 0,
 		  .chantype = -1 },
+		{ .name = "160MHz",
+		  .width = NL80211_CHAN_WIDTH_160,
+		  .freq1_diff = 0,
+		  .chantype = -1 },
 	};
 	const struct chanmode *chanmode_selected = NULL;
 	unsigned int freq;
@@ -1233,6 +1237,7 @@
 {
 	unsigned int cf1 = freq, j;
 	unsigned int vht80[] = { 5180, 5260, 5500, 5580, 5660, 5745 };
+	unsigned int vht160[] = { 5180, 5500 };
 
 	switch (chanmode->width) {
 	case NL80211_CHAN_WIDTH_80:
@@ -1247,6 +1252,18 @@
 
 		cf1 = vht80[j] + 30;
 		break;
+	case NL80211_CHAN_WIDTH_160:
+		/* setup center_freq1 */
+		for (j = 0; j < ARRAY_SIZE(vht160); j++) {
+			if (freq >= vht160[j] && freq < vht160[j] + 160)
+				break;
+		}
+
+		if (j == ARRAY_SIZE(vht160))
+			break;
+
+		cf1 = vht160[j] + 70;
+		break;
 	default:
 		cf1 = freq + chanmode->freq1_diff;
 		break;