From ff55daf1eb8b96f09fceeaf62b882ba0b7dfa34b Mon Sep 17 00:00:00 2001 From: David Bauer Date: Sun, 4 May 2025 04:49:50 +0200 Subject: [PATCH 01/17] ramips: drop ALT0 name from Pulse EX400 dts model The alternative model name does not need to be represented in the DTS. Signed-off-by: David Bauer --- target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts index 2ec6498322..7256ea0cf2 100644 --- a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts +++ b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts @@ -4,7 +4,7 @@ / { compatible = "genexis,pulse-ex400", "mediatek,mt7621-soc"; - model = "Genexis/Inteno Pulse EX400"; + model = "Genexis Pulse EX400"; aliases { led-boot = &led_status_red; From 0842e793381a1e60f8acdcbea0e8c59be1ac9a88 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Sun, 4 May 2025 04:47:32 +0200 Subject: [PATCH 02/17] ramips: add Semtech SX9512 touch input driver This driver is required for the touch-inputs as well as some LEDs on the Genexis Pulse EX400. The driver was also sent upstream. As the EX400 is currently the only consumer, the driver is added target-specific for ramips. Once the driver has been accepted upstream and is provided in a kernel release used by OpenWrt, the package should be moved to the global input drivers. Link: https://www.spinics.net/lists/kernel/msg5669349.html Signed-off-by: David Bauer --- target/linux/ramips/modules.mk | 18 + ...51x-add-Semtech-SX9512-SX9513-driver.patch | 560 ++++++++++++++++++ 2 files changed, 578 insertions(+) create mode 100644 target/linux/ramips/patches-6.6/870-Input-sx951x-add-Semtech-SX9512-SX9513-driver.patch diff --git a/target/linux/ramips/modules.mk b/target/linux/ramips/modules.mk index 175ba94eff..22a9660b0f 100644 --- a/target/linux/ramips/modules.mk +++ b/target/linux/ramips/modules.mk @@ -152,3 +152,21 @@ define KernelPackage/sound-mt7620/description endef $(eval $(call KernelPackage,sound-mt7620)) + + +define KernelPackage/keyboard-sx951x + SUBMENU:=Other modules + TITLE:=Semtech SX9512/SX9513 + DEPENDS:=@TARGET_ramips_mt7621 +kmod-input-core + KCONFIG:= \ + CONFIG_KEYBOARD_SX951X \ + CONFIG_INPUT_KEYBOARD=y + FILES:=$(LINUX_DIR)/drivers/input/keyboard/sx951x.ko + AUTOLOAD:=$(call AutoProbe,sx951x) +endef + +define KernelPackage/keyboard-sx951x/description + Enable support for SX9512/SX9513 capacitive touch controllers +endef + +$(eval $(call KernelPackage,keyboard-sx951x)) diff --git a/target/linux/ramips/patches-6.6/870-Input-sx951x-add-Semtech-SX9512-SX9513-driver.patch b/target/linux/ramips/patches-6.6/870-Input-sx951x-add-Semtech-SX9512-SX9513-driver.patch new file mode 100644 index 0000000000..340fb3c342 --- /dev/null +++ b/target/linux/ramips/patches-6.6/870-Input-sx951x-add-Semtech-SX9512-SX9513-driver.patch @@ -0,0 +1,560 @@ +From ba92c0187006e2a6eae9573a569d275b0bd31732 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Fri, 2 May 2025 23:04:27 +0200 +Subject: [PATCH] Input sx951x: add Semtech SX9512/SX9513 driver + +The Semtech SX9512/SX9513 is a family of capacitive touch-keyboard +controllers. + +All chips offer 8 channel touch sensitive inputs with one LED driver per +output channel. + +The also SX9512 supports proximity detection which is currently not +supported with the driver. + +This chip can be found on the Genexis Pulse EX400 repeater platform. + +Link: https://www.mouser.com/datasheet/2/761/SEMTS05226_1-2575172.pdf +Link: https://www.spinics.net/lists/kernel/msg5669349.html + +Signed-off-by: David Bauer +--- + drivers/input/keyboard/Kconfig | 11 + + drivers/input/keyboard/Makefile | 1 + + drivers/input/keyboard/sx951x.c | 490 ++++++++++++++++++++++++++++++++ + 3 files changed, 502 insertions(+) + create mode 100644 drivers/input/keyboard/sx951x.c + +diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig +index 1d0c5f4c0f99..6dc397389c64 100644 +--- a/drivers/input/keyboard/Kconfig ++++ b/drivers/input/keyboard/Kconfig +@@ -616,6 +616,17 @@ config KEYBOARD_SUNKBD + To compile this driver as a module, choose M here: the + module will be called sunkbd. + ++config KEYBOARD_SX951X ++ tristate "Semtech SX951X capacitive touch controller" ++ depends on OF && I2C ++ select REGMAP_I2C ++ help ++ Say Y here to enable the Semtech SX9512/SX9153 capacitive ++ touch controller driver. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called sx951x. ++ + config KEYBOARD_SH_KEYSC + tristate "SuperH KEYSC keypad support" + depends on ARCH_SHMOBILE || COMPILE_TEST +diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile +index aecef00c5d09..e59ca83c30ec 100644 +--- a/drivers/input/keyboard/Makefile ++++ b/drivers/input/keyboard/Makefile +@@ -66,6 +66,7 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o + obj-$(CONFIG_KEYBOARD_ST_KEYSCAN) += st-keyscan.o + obj-$(CONFIG_KEYBOARD_SUN4I_LRADC) += sun4i-lradc-keys.o + obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o ++obj-$(CONFIG_KEYBOARD_SX951X) += sx951x.o + obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o + obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o + obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY) += tm2-touchkey.o +diff --git a/drivers/input/keyboard/sx951x.c b/drivers/input/keyboard/sx951x.c +new file mode 100644 +index 000000000000..66355036aa95 +--- /dev/null ++++ b/drivers/input/keyboard/sx951x.c +@@ -0,0 +1,490 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Input driver for Semtech SX9512/SX9513 capacitive touch sensors. ++ * ++ * The difference between SX9512 and SX9513 is the presence of proximity ++ * sensing capabilities on the SX9512. ++ * ++ * SX951xB is the identical chip but with a different I2C address. ++ * ++ * (c) 2025 David Bauer ++ */ ++ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ ++ /* Generic properties */ ++#define SX951X_I2C_ADDRESS 0x2b ++#define SX951XB_I2C_ADDRESS_ 0x2d ++#define SX951X_NUM_CHANNELS 8 ++#define SX951X_POLL_INTERVAL 100 ++ ++/* Registers*/ ++#define SX951X_REG_IRQ_SRC 0x00 ++#define SX951X_REG_TOUCH_STATUS 0x01 ++#define SX951X_REG_PROXIMITY_STATUS 0x02 ++#define SX951X_REG_COMPENSATION_STATUS 0x03 ++#define SX951X_REG_IRQ_NVM_CTRL 0x04 ++#define SX951X_REG_SPO2_MODE_CTRL 0x07 ++#define SX951X_REG_PWR_KEY_CTRL 0x08 ++#define SX951X_REG_IRQ_MASK 0x09 ++ ++/* LED registers */ ++#define SX951X_REG_LED_MAP_ENG1 0x0c ++#define SX951X_REG_LED_MAP_ENG2 0x0d ++#define SX951X_REG_LED_PWM_FREQ 0x0e ++#define SX951X_REG_LED_MODE 0x0f ++#define SX951X_REG_LED_IDLE 0x10 ++#define SX951X_REG_LED_OFF_DELAY 0x11 ++#define SX951X_REG_LED_ON_ENG1 0x12 ++#define SX951X_REG_LED_FADE_ENG1 0x13 ++#define SX951X_REG_LED_ON_ENG2 0x14 ++#define SX951X_REG_LED_FADE_ENG2 0x15 ++#define SX951X_REG_LED_POWER_IDLE 0x16 ++#define SX951X_REG_LED_POWER_ON 0x17 ++#define SX951X_REG_LED_POWER_OFF 0x18 ++#define SX951X_REG_LED_POWER_FADE 0x19 ++#define SX951X_REG_LED_POWER_ON_PULSE 0x1a ++#define SX951X_REG_LED_POWER_MODE 0x1b ++ ++/* Capacitive touch sensing registers*/ ++#define SX951X_REG_CAP_SENSE_ENABLE 0x1e ++ ++#define SX951X_REG_CAP_SENSE_RANGE(x) (0x1f + (x)) ++#define SX951X_REG_CAP_SENSE_RANGE_CIN_DELTA_MASK GENMASK(1, 0) ++ ++#define SX951X_REG_CAP_SENSE_THRESH(x) (0x28 + (x)) ++#define SX951X_REG_CAP_SENSE_THRESH_ALL 0x30 ++ ++#define SX951X_REG_CAP_SENSE_OP 0x31 ++#define SX951X_REG_CAP_SENSE_MODE 0x32 ++#define SX951X_REG_CAP_SENSE_DEBOUNCE 0x33 ++ ++/* Reset register*/ ++#define SX951X_REG_SOFT_RESET 0xff ++ ++/* Default properties (keys)*/ ++#define SX951X_KEY_DEFAULT_CIN_DELTA 0x03 ++#define SX951X_KEY_DEFAULT_SENSE_THRESHOLD 0x04 ++ ++struct sx951x_key_data { ++ u32 cin_delta; ++ u32 sense_threshold; ++}; ++ ++struct sx951x_led { ++#ifdef CONFIG_LEDS_CLASS ++ struct led_classdev cdev; ++ struct sx951x_priv *priv; ++ ++ u32 reg; ++ bool registered; ++#endif ++}; ++ ++struct sx951x_priv { ++ struct regmap *regmap; ++ struct device *dev; ++ struct input_dev *idev; ++ const struct sx951x_hw_data *hw; ++ ++ struct sx951x_led leds[SX951X_NUM_CHANNELS]; ++ ++ /* device-config */ ++ u32 poll_interval; ++ ++ /* key-config */ ++ u32 keycodes[SX951X_NUM_CHANNELS]; ++ struct sx951x_key_data key_data[SX951X_NUM_CHANNELS]; ++}; ++ ++struct sx951x_hw_data { ++ bool has_proximity_sensing; ++}; ++ ++static const struct reg_default sx951x_reg_defaults[] = { ++ { SX951X_REG_LED_MAP_ENG1, 0x00 }, ++ { SX951X_REG_LED_MAP_ENG2, 0x00 }, ++ { SX951X_REG_LED_PWM_FREQ, 0x10 }, ++ { SX951X_REG_LED_IDLE, 0xff }, ++ { SX951X_REG_LED_ON_ENG1, 0xff }, ++ { SX951X_REG_LED_ON_ENG2, 0xff }, ++ { SX951X_REG_LED_POWER_IDLE, 0xff }, ++ { SX951X_REG_LED_POWER_ON, 0xff }, ++ { SX951X_REG_CAP_SENSE_ENABLE, 0x00 }, ++ { SX951X_REG_CAP_SENSE_RANGE(0), 0x40 }, ++ { SX951X_REG_CAP_SENSE_RANGE(1), 0x40 }, ++ { SX951X_REG_CAP_SENSE_RANGE(2), 0x40 }, ++ { SX951X_REG_CAP_SENSE_RANGE(3), 0x40 }, ++ { SX951X_REG_CAP_SENSE_RANGE(4), 0x40 }, ++ { SX951X_REG_CAP_SENSE_RANGE(5), 0x40 }, ++ { SX951X_REG_CAP_SENSE_RANGE(6), 0x40 }, ++ { SX951X_REG_CAP_SENSE_RANGE(7), 0x40 }, ++ { SX951X_REG_CAP_SENSE_THRESH(0), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH(1), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH(2), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH(3), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH(4), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH(5), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH(6), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH(7), 0x0f }, ++ { SX951X_REG_CAP_SENSE_THRESH_ALL, 0x0f }, ++ { SX951X_REG_CAP_SENSE_OP, 0x14 }, ++ { SX951X_REG_CAP_SENSE_MODE, 0x70 }, ++ { SX951X_REG_CAP_SENSE_DEBOUNCE, 0xff }, ++}; ++ ++static bool sx951x_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case SX951X_REG_TOUCH_STATUS: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static const struct regmap_config sx951x_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ ++ .max_register = SX951X_REG_SOFT_RESET, ++ ++ .reg_defaults = sx951x_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(sx951x_reg_defaults), ++ ++ .cache_type = REGCACHE_MAPLE, ++ .volatile_reg = sx951x_volatile_reg, ++}; ++ ++#ifdef CONFIG_LEDS_CLASS ++static int sx951x_led_set(struct led_classdev *cdev, enum led_brightness value) ++{ ++ struct sx951x_led *led = container_of(cdev, struct sx951x_led, cdev); ++ struct sx951x_priv *priv = led->priv; ++ ++ return regmap_update_bits(priv->regmap, ++ SX951X_REG_LED_MAP_ENG2, ++ BIT(led->reg), ++ value ? BIT(led->reg) : 0); ++} ++ ++static int sx951x_led_init(struct sx951x_priv *priv, ++ struct device_node *channel_node, u32 reg) ++{ ++ struct device_node *led_node; ++ struct sx951x_led *led = &priv->leds[reg]; ++ struct led_init_data init_data = {}; ++ int error; ++ ++ if (led->registered) { ++ dev_err(priv->dev, ++ "LED %d already registered\n", reg); ++ return -EINVAL; ++ } ++ ++ led_node = of_get_child_by_name(channel_node, "led"); ++ if (!led_node) { ++ /* No LED */ ++ return 0; ++ } ++ ++ led->cdev.flags = 0; ++ led->cdev.brightness_set_blocking = sx951x_led_set; ++ led->cdev.max_brightness = 1; ++ led->cdev.brightness = LED_OFF; ++ ++ init_data.default_label = of_get_property(led_node, "label", NULL); ++ init_data.fwnode = of_fwnode_handle(led_node); ++ ++ led->reg = reg; ++ led->priv = priv; ++ ++ error = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data); ++ if (error) ++ return error; ++ ++ return 0; ++} ++#endif ++ ++static void sx951x_poll(struct input_dev *input) ++{ ++ struct sx951x_priv *priv = input_get_drvdata(input); ++ struct device *dev = priv->dev; ++ unsigned int val; ++ int error; ++ int i; ++ ++ error = regmap_read(priv->regmap, SX951X_REG_TOUCH_STATUS, &val); ++ if (error) { ++ dev_err(dev, "Failed to read touch status: %d\n", error); ++ return; ++ } ++ ++ for (i = 0; i < SX951X_NUM_CHANNELS; i++) { ++ if (priv->keycodes[i] == KEY_RESERVED) ++ continue; ++ ++ input_report_key(input, priv->keycodes[i], !!(val & BIT(i))); ++ input_sync(input); ++ } ++} ++ ++static int sx951x_channel_init(struct sx951x_priv *priv, struct device_node *of_node, ++ u32 chan_idx) ++{ ++ struct sx951x_key_data *key_data; ++ struct device *dev = priv->dev; ++ int error; ++ ++ key_data = &priv->key_data[chan_idx]; ++ ++ /* Defaults */ ++ key_data->cin_delta = SX951X_KEY_DEFAULT_CIN_DELTA; ++ key_data->sense_threshold = SX951X_KEY_DEFAULT_SENSE_THRESHOLD; ++ ++ error = of_property_read_u32(of_node, "linux,keycodes", ++ &priv->keycodes[chan_idx]); ++ if (error) { ++ /* Not configured */ ++ return 0; ++ } ++ ++ error = of_property_read_u32(of_node, "semtech,cin-delta", ++ &key_data->cin_delta); ++ if (key_data->cin_delta > 0x03) { ++ dev_err(dev, "Failed to read cin-delta for channel %d: %d\n", ++ chan_idx, error); ++ return error; ++ } ++ ++ error = of_property_read_u32(of_node, "semtech,sense-threshold", ++ &key_data->sense_threshold); ++ if (key_data->sense_threshold > 0xff) { ++ dev_err(dev, "Failed to read sense-threshold for channel %d: %d\n", ++ chan_idx, error); ++ return error; ++ } ++ ++ error = regmap_update_bits(priv->regmap, ++ SX951X_REG_CAP_SENSE_RANGE(chan_idx), ++ SX951X_REG_CAP_SENSE_RANGE_CIN_DELTA_MASK, ++ key_data->cin_delta); ++ ++ if (error) { ++ dev_err(dev, "Failed to set cin-delta for channel %d: %d\n", ++ chan_idx, error); ++ return error; ++ } ++ ++ error = regmap_write(priv->regmap, ++ SX951X_REG_CAP_SENSE_THRESH(chan_idx), ++ key_data->sense_threshold); ++ if (error) { ++ dev_err(dev, "Failed to set sense-threshold for channel %d: %d\n", ++ chan_idx, error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int sx951x_channels_init(struct sx951x_priv *priv) ++{ ++ struct device *dev = priv->dev; ++ unsigned int channels = 0; ++ int error; ++ u32 reg; ++ ++ for_each_child_of_node_scoped(dev->of_node, child) { ++ error = of_property_read_u32(child, "reg", ®); ++ if (error != 0 || reg >= SX951X_NUM_CHANNELS) { ++ dev_err(dev, "Invalid channel %d\n", reg); ++ return -EINVAL; ++ } ++ ++ priv->keycodes[reg] = KEY_RESERVED; ++ ++ error = sx951x_channel_init(priv, child, reg); ++ if (error) { ++ dev_err(dev, "Failed to initialize channel %d: %d\n", ++ reg, error); ++ return error; ++ } ++ ++ if (priv->keycodes[reg] != KEY_RESERVED) ++ channels |= BIT(reg); ++ ++#ifdef CONFIG_LEDS_CLASS ++ error = sx951x_led_init(priv, child, reg); ++ if (error) { ++ dev_err(dev, "Failed to initialize LED %d: %d\n", ++ reg, error); ++ return error; ++ } ++#endif ++ } ++ ++ /* Enable sensing on channels with keycode configured */ ++ error = regmap_write(priv->regmap, ++ SX951X_REG_CAP_SENSE_ENABLE, ++ channels); ++ ++ return 0; ++} ++ ++static int sx951x_input_init(struct sx951x_priv *priv) ++{ ++ struct device *dev = priv->dev; ++ int i, error; ++ ++ priv->idev = devm_input_allocate_device(dev); ++ if (!priv->idev) ++ return -ENOMEM; ++ ++ priv->idev->name = "SX9512/SX9513 capacitive touch sensor"; ++ priv->idev->id.bustype = BUS_I2C; ++ __set_bit(EV_KEY, priv->idev->evbit); ++ ++ for (i = 0; i < SX951X_NUM_CHANNELS; i++) ++ __set_bit(priv->keycodes[i], priv->idev->keybit); ++ ++ __clear_bit(KEY_RESERVED, priv->idev->keybit); ++ ++ priv->idev->keycode = priv->keycodes; ++ priv->idev->keycodesize = sizeof(priv->keycodes[0]); ++ priv->idev->keycodemax = SX951X_NUM_CHANNELS; ++ ++ input_set_drvdata(priv->idev, priv); ++ ++ error = input_setup_polling(priv->idev, sx951x_poll); ++ if (error) { ++ dev_err(dev, "Unable to set up polling: %d\n", error); ++ return error; ++ } ++ ++ input_set_poll_interval(priv->idev, priv->poll_interval); ++ ++ error = input_register_device(priv->idev); ++ if (error) { ++ dev_err(dev, "Unable to register polled device: %d\n", ++ error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int sx951x_probe(struct i2c_client *i2c_client) ++{ ++ const struct i2c_device_id *id; ++ const struct sx951x_hw_data *hw; ++ struct device *dev = &i2c_client->dev; ++ struct sx951x_priv *priv; ++ int error; ++ ++ if (i2c_client->addr != SX951X_I2C_ADDRESS && ++ i2c_client->addr != SX951XB_I2C_ADDRESS_) { ++ dev_err(dev, "Invalid I2C address: 0x%02x\n", ++ i2c_client->addr); ++ return -ENODEV; ++ } ++ ++ id = i2c_client_get_device_id(i2c_client); ++ hw = i2c_get_match_data(i2c_client); ++ if (!id || !hw) { ++ dev_err(dev, "Invalid device configuration\n"); ++ return -EINVAL; ++ } ++ ++ priv = devm_kzalloc(dev, ++ sizeof(struct sx951x_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = dev; ++ priv->hw = hw; ++ ++ priv->regmap = devm_regmap_init_i2c(i2c_client, &sx951x_regmap_config); ++ if (IS_ERR(priv->regmap)) ++ return PTR_ERR(priv->regmap); ++ ++ /* Parse device configuration */ ++ if (of_property_read_u32(dev->of_node, "poll-interval", ++ &priv->poll_interval)) ++ priv->poll_interval = SX951X_POLL_INTERVAL; ++ ++ /* Register LED and input channels */ ++ error = sx951x_channels_init(priv); ++ if (error) { ++ dev_err(dev, "Failed to initialize channels: %d\n", error); ++ return error; ++ } ++ ++ /* Register input device */ ++ error = sx951x_input_init(priv); ++ if (error) { ++ dev_err(dev, "Failed to register input device: %d\n", error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static void sx951x_remove(struct i2c_client *i2c_client) ++{ ++ struct sx951x_priv *priv = i2c_get_clientdata(i2c_client); ++ ++ /* Disable sensing */ ++ regmap_write(priv->regmap, SX951X_REG_CAP_SENSE_ENABLE, 0x00); ++ ++ /* Turn off all LEDs */ ++ regmap_write(priv->regmap, SX951X_REG_LED_MAP_ENG2, 0x00); ++} ++ ++static const struct sx951x_hw_data sx9512_hw_data = { ++ .has_proximity_sensing = true, ++}; ++ ++static const struct sx951x_hw_data sx9513_hw_data = { ++ .has_proximity_sensing = false, ++}; ++ ++static const struct of_device_id sx951x_dt_ids[] = { ++ { .compatible = "semtech,sx9512", .data = &sx9512_hw_data }, ++ { .compatible = "semtech,sx9513", .data = &sx9513_hw_data }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sx951x_dt_ids); ++ ++static const struct i2c_device_id sx951x_i2c_ids[] = { ++ { "sx9512", (kernel_ulong_t)&sx9512_hw_data }, ++ { "sx9513", (kernel_ulong_t)&sx9513_hw_data }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, sx951x_i2c_ids); ++ ++static struct i2c_driver sx951x_i2c_driver = { ++ .driver = { ++ .name = "sx951x", ++ .of_match_table = sx951x_dt_ids, ++ }, ++ .id_table = sx951x_i2c_ids, ++ .probe = sx951x_probe, ++ .remove = sx951x_remove, ++}; ++ ++module_i2c_driver(sx951x_i2c_driver); ++ ++MODULE_DESCRIPTION("Semtech SX9512/SX9513 driver"); ++MODULE_AUTHOR("David Bauer "); ++MODULE_LICENSE("GPL"); +-- +2.47.2 + From 49a1781d74590f0945973dac6d82faeb2f624b6f Mon Sep 17 00:00:00 2001 From: David Bauer Date: Sun, 4 May 2025 04:45:03 +0200 Subject: [PATCH 03/17] ramips: support Genexis EX400 touch controller Add the necessary package dependencies as well as device-tree properties to support the touch-inputs as well as missing LEDs on the Genexis Pulse EX400 range extender. Signed-off-by: David Bauer --- .../ramips/dts/mt7621_genexis_pulse-ex400.dts | 82 +++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 2 +- .../mt7621/base-files/etc/board.d/01_leds | 1 + 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts index 7256ea0cf2..61b3e869d7 100644 --- a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts +++ b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts @@ -21,3 +21,85 @@ gpios = <&gpio 12 GPIO_ACTIVE_LOW>; }; }; + +&i2c { + clock-frequency = <1000>; + + touch@2b { + compatible = "semtech,sx9512"; + + reg = <0x2b>; + + #address-cells = <1>; + #size-cells = <0>; + + poll-interval = <150>; + + /* Touch area 2.4 GHz */ + channel@1 { + reg = <1>; + + semtech,cin-delta = <0x3>; + semtech,sense-threshold = <0x04>; + + linux,keycodes = ; + }; + + /* Touch area 5 GHz */ + channel@2 { + reg = <2>; + + semtech,cin-delta = <0x3>; + semtech,sense-threshold = <0x04>; + + linux,keycodes = ; + }; + /* Touch area WPS */ + channel@3 { + reg = <3>; + + semtech,cin-delta = <0x3>; + semtech,sense-threshold = <0x04>; + + linux,keycodes = ; + }; + + channel@4 { + reg = <4>; + + led { + color = ; + function = LED_FUNCTION_WAN; + }; + }; + + channel@5 { + reg = <5>; + + led { + color = ; + function = LED_FUNCTION_WAN; + }; + }; + + channel@6 { + reg = <6>; + + led { + color = ; + function = LED_FUNCTION_WLAN_5GHZ; + linux,default-trigger = "phy1tpt"; + }; + }; + + channel@7 { + reg = <7>; + + led { + color = ; + function = LED_FUNCTION_WLAN_2GHZ; + linux,default-trigger = "phy0tpt"; + }; + }; + }; +}; \ No newline at end of file diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 69c91dd69c..5e1cec135c 100755 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1411,7 +1411,7 @@ endif IMAGE/sysupgrade.bin := append-kernel | inteno-bootfs | \ sysupgrade-tar kernel=$$$$@ | check-size | append-metadata DEVICE_IMG_NAME = $$(DEVICE_IMG_PREFIX)-$$(2) - DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615-firmware kmod-usb3 + DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615-firmware kmod-usb3 kmod-keyboard-sx951x kmod-button-hotplug endef define Device/genexis_pulse-ex400 diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index e268a089a5..ab00c671b3 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -59,6 +59,7 @@ belkin,rt1800) ucidef_set_led_netdev "wan" "wan" "white:wan" "wan" ;; confiabits,mt7621-v1|\ +genexis,pulse-ex400|\ netis,n6) ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx" ;; From f828be4d10d795e2bd74ea77ea12dec285107974 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Tue, 6 May 2025 18:23:50 +0200 Subject: [PATCH 04/17] ramips: use i2c-gpio driver for EX400 Configure the i2c pins as GPIO outputs and use the i2c-gpio driver to control the Semtech SX9512 touch controller. This fixes spurious errors in i2c transactions even at 1kHz with the native i2c driver. leds green:wan: Setting an LED's brightness failed (-6) Signed-off-by: David Bauer --- .../dts/mt7621_genexis_pulse-ex400-common.dtsi | 17 +++++++++++++++-- .../ramips/dts/mt7621_genexis_pulse-ex400.dts | 4 +--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400-common.dtsi b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400-common.dtsi index a3bc70e8ce..ebcf558359 100644 --- a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400-common.dtsi +++ b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400-common.dtsi @@ -41,6 +41,18 @@ gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; }; }; + + i2c_gpio: i2c-gpio { + compatible = "i2c-gpio"; + + sda-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>; + + i2c-gpio,delay-us = <50>; + i2c-gpio,timeout-ms = <100>; + + /* Semtech SX9512 */ + }; }; &pcie { @@ -92,7 +104,8 @@ }; &i2c { - status = "okay"; + /* Uses i2c-gpio */ + status = "disabled"; }; ðphy0 { @@ -101,7 +114,7 @@ &state_default { gpio { - groups = "uart2", "uart3"; + groups = "i2c", "uart2", "uart3"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts index 61b3e869d7..ad8a22ad79 100644 --- a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts +++ b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts @@ -22,9 +22,7 @@ }; }; -&i2c { - clock-frequency = <1000>; - +&i2c_gpio { touch@2b { compatible = "semtech,sx9512"; From 75403dd1d05bea1b65349ebb9f8b7deb40b9c802 Mon Sep 17 00:00:00 2001 From: David DeGraw Date: Fri, 18 Apr 2025 11:55:34 -0600 Subject: [PATCH 05/17] ramips: add support for Cudy R700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the same hardware as the Cudy WR2100 that's had support for some time now, just without the WLAN hardware. This PR is mostly copied from the commit that added support for the WR2100, here: 3501db9 Specifications: SoC: MT7621 CPU: 880 MHz Flash: 16 MiB RAM: 128 MiB Ethernet: 5x Gbit ports Installation: There are two known options: The Luci-based UI. Press and hold the reset button during power up. The router will request 'recovery.bin' from a TFTP server at 192.168.1.88. Both options require a signed firmware binary. A signed firmware can be found in GitHub PR #18532. R4 & R5 need to be shorted (0-100Ω) for the UART to work. Link: https://github.com/openwrt/openwrt/pull/18532 Signed-off-by: David DeGraw --- target/linux/ramips/dts/mt7621_cudy_r700.dts | 203 ++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 10 + .../mt7621/base-files/etc/board.d/01_leds | 1 + 3 files changed, 214 insertions(+) create mode 100644 target/linux/ramips/dts/mt7621_cudy_r700.dts diff --git a/target/linux/ramips/dts/mt7621_cudy_r700.dts b/target/linux/ramips/dts/mt7621_cudy_r700.dts new file mode 100644 index 0000000000..6d1c1ec004 --- /dev/null +++ b/target/linux/ramips/dts/mt7621_cudy_r700.dts @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621.dtsi" + +#include +#include +#include + +/ { + compatible = "cudy,r700", "mediatek,mt7621-soc"; + model = "Cudy R700"; + + aliases { + led-boot = &led_internet_blue; + led-failsafe = &led_internet_blue; + led-running = &led_internet_blue; + led-upgrade = &led_internet_blue; + label-mac-device = &gmac0; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_internet_blue: internet_blue { + label = "blue:internet"; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + }; + + internet_red { + label = "red:internet"; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; + }; + + wan { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "green:lan1"; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "green:lan2"; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; + }; + + lan3 { + label = "green:lan3"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + }; + + lan4 { + label = "green:lan4"; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_bdinfo_de00 0>; + nvmem-cell-names = "mac-address"; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + }; + }; + + partition@50000 { + compatible = "denx,uimage"; + label = "firmware"; + reg = <0x50000 0xf80000>; + }; + + partition@fd0000 { + label = "debug"; + reg = <0xfd0000 0x10000>; + read-only; + }; + + partition@fe0000 { + label = "backup"; + reg = <0xfe0000 0x10000>; + read-only; + }; + + partition@ff0000 { + label = "bdinfo"; + reg = <0xff0000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_de00: macaddr@de00 { + compatible = "mac-base"; + reg = <0xde00 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; +}; + +&state_default { + gpio { + groups = "i2c", "jtag", "uart3", "wdt"; + function = "gpio"; + }; +}; + +&gmac1 { + status = "okay"; + label = "wan"; + phy-handle = <ðphy4>; + + nvmem-cells = <&macaddr_bdinfo_de00 1>; + nvmem-cell-names = "mac-address"; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + }; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 5e1cec135c..943c11565a 100755 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -768,6 +768,16 @@ define Device/cudy_wr2100 endef TARGET_DEVICES += cudy_wr2100 +define Device/cudy_r700 + $(Device/dsa-migration) + DEVICE_VENDOR := Cudy + DEVICE_MODEL := R700 + IMAGE_SIZE := 15872k + UIMAGE_NAME := R29 + DEVICE_PACKAGES := -uboot-envtools +endef +TARGET_DEVICES += cudy_r700 + define Device/cudy_x6-v1 $(Device/dsa-migration) IMAGE_SIZE := 32256k diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index ab00c671b3..841a8374fe 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -63,6 +63,7 @@ genexis,pulse-ex400|\ netis,n6) ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx" ;; +cudy,r700|\ cudy,wr2100) ucidef_set_led_netdev "lan1" "lan1" "green:lan1" "lan1" ucidef_set_led_netdev "lan2" "lan2" "green:lan2" "lan2" From e4b8279b7e85cba9213164e4e9373784059206f7 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Sun, 30 Mar 2025 19:33:31 +0200 Subject: [PATCH 06/17] lantiq: xrx200_legacy: rename PHY LEDs This commit corrects led phy names. This has been discussed at link [1] and corrected in the mediatek target in the commit a51fd20e0d65ef836ee6c1e13c39a529855af4a0. Now it's time to do the same thing in the lantiq target. Link: https://github.com/openwrt/openwrt/pull/18265 Signed-off-by: Aleksander Jan Bajkowski --- .../arch/mips/boot/dts/lantiq/vr9_arcadyan_vg3503j.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9_arcadyan_vg3503j.dts b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9_arcadyan_vg3503j.dts index b7cdf9d569..478934c2c1 100644 --- a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9_arcadyan_vg3503j.dts +++ b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9_arcadyan_vg3503j.dts @@ -79,14 +79,14 @@ #address-cells = <1>; #size-cells = <0>; - led-1 { + led@1 { reg = <1>; color = ; function = LED_FUNCTION_LAN; }; - led-2 { + led@2 { reg = <2>; color = ; function = LED_FUNCTION_LAN; @@ -101,14 +101,14 @@ #address-cells = <1>; #size-cells = <0>; - led-1 { + led@1 { reg = <1>; color = ; function = LED_FUNCTION_LAN; }; - led-2 { + led@2 { reg = <2>; color = ; function = LED_FUNCTION_LAN; From a3da25c62b70256300772736ea6080e83a7cc0c2 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Sun, 30 Mar 2025 19:34:57 +0200 Subject: [PATCH 07/17] lantiq: xrx200_legacy: rename TP-LINK to TP-Link Keep the name consistent with other places. Signed-off-by: Aleksander Jan Bajkowski --- target/linux/lantiq/image/tp-link_legacy.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/lantiq/image/tp-link_legacy.mk b/target/linux/lantiq/image/tp-link_legacy.mk index 313fe11e63..c33872f8d9 100644 --- a/target/linux/lantiq/image/tp-link_legacy.mk +++ b/target/linux/lantiq/image/tp-link_legacy.mk @@ -38,10 +38,10 @@ define Device/tplink_tdw8980 $(Device/lantiqTpLink) DEVICE_MODEL := TD-W8980 DEVICE_VARIANT := v1 - DEVICE_ALT0_VENDOR := TP-LINK + DEVICE_ALT0_VENDOR := TP-Link DEVICE_ALT0_MODEL := TD-W9980 DEVICE_ALT0_VARIANT := v1 - DEVICE_ALT1_VENDOR := TP-LINK + DEVICE_ALT1_VENDOR := TP-Link DEVICE_ALT1_MODEL := TD-W9980B DEVICE_ALT1_VARIANT := v1 TPLINK_FLASHLAYOUT := 8Mltq From 739820468318877bce461d37fd2a40c957b82ce6 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 29 Apr 2025 20:52:59 +0800 Subject: [PATCH 08/17] nat46: bump to latest git HEAD 2025-04-23 This new version introduces many compilation error fixes for the upcoming 6.12 kernel. Changelogs: 04923c5 "Fix build failures observed so far" - take three. b4263cc "Fix build failures observed so far" - take two. de595b4 Fix build failures observed so far 1c0066a Zero checksum handling for UDP4->UDP6 b42c37d Fix crash when viewing nat46 kernel module config 3a9f630 nat46-module: fix modpost warning 88b91ca gha: use checkout@v4 action instead of checkout@v2 84ba13a gha: enable github action on push/PR f367088 fix the compilation error 03c14bf gha: clean-up the yaml definition d964921 Create c-compile.yml cb69317 "Add network namespace awareness to nat46" - take two. 8302f42 Revert "Add network namespace awareness to nat46" 91b8e68 Add network namespace awareness to nat46 Signed-off-by: Shiji Yang --- package/kernel/nat46/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/kernel/nat46/Makefile b/package/kernel/nat46/Makefile index 296ef5a058..f793997508 100644 --- a/package/kernel/nat46/Makefile +++ b/package/kernel/nat46/Makefile @@ -3,11 +3,11 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=nat46 -PKG_MIRROR_HASH:=09b93f31d10030d3b4f326066b544b70b1f60236d0482f27c384ed93b298c0a6 +PKG_MIRROR_HASH:=35d7987eed7f05e5f7d1d2e111a8c9f5d019ccf11eb839dfe0bd2e2c46b6199a PKG_SOURCE_URL:=https://github.com/ayourtch/nat46.git -PKG_SOURCE_DATE:=2022-09-19 +PKG_SOURCE_DATE:=2025-04-23 PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=4c5beee236841724219598fabb1edc93d4f08ce5 +PKG_SOURCE_VERSION:=04923c51039e8ca270c6f1dde3f04f3b36958089 PKG_MAINTAINER:=Hans Dedecker PKG_LICENSE:=GPL-2.0 From ba6aacd2b8ff865ce76d9041aa75334ce8c8420c Mon Sep 17 00:00:00 2001 From: Gustavo Bertoli Date: Wed, 12 Mar 2025 18:22:12 +0100 Subject: [PATCH 09/17] hostapd: Enable DPPv2 support for OpenSSL and mbedtls Enable Device Provisioning Protocol (DPPv2) in hostapd for the "full" build-variants. DPPv2 currently does not compile with WolfSSL due to missing PKCS7 and certificate support. Link: https://github.com/openwrt/openwrt/pull/18485 Signed-off-by: Gustavo Bertoli --- package/network/services/hostapd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile index e2a0a1e70a..2e04540675 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hostapd -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL:=https://w1.fi/hostap.git PKG_SOURCE_PROTO:=git @@ -110,7 +110,7 @@ ifeq ($(SSL_VARIANT),openssl) DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y endif ifeq ($(LOCAL_VARIANT),full) - DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_EAP_PWD=y + DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_EAP_PWD=y CONFIG_DPP=y CONFIG_DPP2=y endif endif @@ -140,7 +140,7 @@ ifeq ($(SSL_VARIANT),mbedtls) DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1 endif ifeq ($(LOCAL_VARIANT),full) - DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1 CONFIG_EAP_PWD=y + DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1 CONFIG_EAP_PWD=y CONFIG_DPP=y CONFIG_DPP2=y endif endif From 3d9236d4512c5cfca9cbe6c452f56d3a682c2ada Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Sat, 29 Mar 2025 23:39:19 +0100 Subject: [PATCH 10/17] iw: backport WiFi 7 (EHT) scan support Backport patches to support scans of WiFi 7 APs. Signed-off-by: Aleksander Jan Bajkowski Link: https://github.com/openwrt/openwrt/pull/18741 Signed-off-by: Robert Marko --- package/network/utils/iw/Makefile | 2 +- ...103-iw-scan-add-enum-for-element-IDs.patch | 170 ++++++ ...ace-passed-ie-buffer-with-ie-context.patch | 482 ++++++++++++++++++ ...pdate-and-clean-up-eht-capa-printing.patch | 207 ++++++++ ...6-iw-scan-add-eht-capability-parsing.patch | 175 +++++++ ...capabilities-on-Big-Endian-platforms.patch | 107 ++++ ...dd-printing-of-EHT-Operation-Element.patch | 131 +++++ .../utils/iw/patches/200-reduce_size.patch | 107 ++-- 8 files changed, 1330 insertions(+), 51 deletions(-) create mode 100644 package/network/utils/iw/patches/103-iw-scan-add-enum-for-element-IDs.patch create mode 100644 package/network/utils/iw/patches/104-iw-scan-replace-passed-ie-buffer-with-ie-context.patch create mode 100644 package/network/utils/iw/patches/105-iw-util-update-and-clean-up-eht-capa-printing.patch create mode 100644 package/network/utils/iw/patches/106-iw-scan-add-eht-capability-parsing.patch create mode 100644 package/network/utils/iw/patches/107-iw-fix-EHT-capabilities-on-Big-Endian-platforms.patch create mode 100644 package/network/utils/iw/patches/108-iw-scan-Add-printing-of-EHT-Operation-Element.patch diff --git a/package/network/utils/iw/Makefile b/package/network/utils/iw/Makefile index c59adbaab5..1734062471 100644 --- a/package/network/utils/iw/Makefile +++ b/package/network/utils/iw/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iw PKG_VERSION:=6.9 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/software/network/iw diff --git a/package/network/utils/iw/patches/103-iw-scan-add-enum-for-element-IDs.patch b/package/network/utils/iw/patches/103-iw-scan-add-enum-for-element-IDs.patch new file mode 100644 index 0000000000..abf699f2ff --- /dev/null +++ b/package/network/utils/iw/patches/103-iw-scan-add-enum-for-element-IDs.patch @@ -0,0 +1,170 @@ +From 966c590bc4dcbd9a69fdf8fe9f41cec00e72e376 Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Mon, 30 Sep 2024 11:11:43 -0700 +Subject: [PATCH] iw: scan: add enum for element IDs + +Formerly, element IDs were hardcoded. Improve readability by using +element ID names. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20240930181145.1043048-2-dylan.eskew@candelatech.com +Signed-off-by: Johannes Berg +--- + ieee80211.h | 43 +++++++++++++++++++++++++++ + scan.c | 86 +++++++++++++++++++++++++++++++---------------------- + 2 files changed, 93 insertions(+), 36 deletions(-) + +--- a/ieee80211.h ++++ b/ieee80211.h +@@ -58,6 +58,49 @@ struct ieee80211_vht_cap { + struct ieee80211_vht_mcs_info mcs; + } __attribute__ ((packed)); + ++enum elem_id { ++ EID_SSID = 0, ++ EID_SUPP_RATES = 1, ++ EID_DS_PARAMS = 3, ++ EID_TIM = 5, ++ EID_IBSS_TIM_PARAMS = 6, ++ EID_COUNTRY = 7, ++ EID_BSS_LOAD = 11, ++ EID_POWER_CONSTRAINT = 32, ++ EID_TPC_REPORT = 35, ++ EID_ERP_INFO = 42, ++ EID_HT_CAPABILITY = 45, ++ EID_ERP_D4_0 = 47, ++ EID_RSN = 48, ++ EID_EXT_SUPP_RATES = 50, ++ EID_AP_CHAN_REPORT = 51, ++ EID_SUPP_OP_CLASSES = 59, ++ EID_HT_OPERATION = 61, ++ EID_SECONDARY_CH_OFFSET = 62, ++ EID_MEASUREMENT_PILOT_TX = 66, ++ EID_RM_ENABLED_CAPABILITIES = 70, ++ EID_OVERLAP_BSS_SCAN_PARAM = 74, ++ EID_INTERWORKING = 107, ++ EID_ADVERTISEMENT = 108, ++ EID_ROAMING_CONSORTIUM = 111, ++ EID_MESH_CONFIG = 113, ++ EID_MESH_ID = 114, ++ EID_EXT_CAPABILITY = 127, ++ EID_VHT_CAPABILITY = 191, ++ EID_VHT_OPERATION = 192, ++ EID_TRANSMIT_POWER_ENVELOPE = 195, ++ EID_SHORT_BEACON_INTERVAL = 214, ++ EID_S1G_CAPABILITY = 217, ++ EID_VENDOR = 221, ++ EID_S1G_OPERATION = 232, ++ EID_EXTENSION = 255, ++}; ++ ++enum elem_id_ext { ++ EID_EXT_HE_CAPABILITY = 35, ++ EID_EXT_HE_OPERATION = 36, ++}; ++ + #define SUITE(oui, id) (((oui) << 8) | (id)) + + /* cipher suite selectors */ +--- a/scan.c ++++ b/scan.c +@@ -1816,40 +1816,54 @@ static void print_ie(const struct ie_pri + } + + static const struct ie_print ieprinters[] = { +- [0] = { "SSID", print_ssid, 0, 32, +- BIT(PRINT_SCAN) | BIT(PRINT_LINK) | BIT(PRINT_LINK_MLO_MLD), }, +- [1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, +- [3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, +- [5] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, +- [6] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), }, +- [7] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), }, +- [11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, +- [32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), }, +- [35] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, +- [42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, +- [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, +- [47] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, +- [51] = { "AP Channel Report", print_ap_channel_report, 1, 255, BIT(PRINT_SCAN), }, +- [59] = { "Supported operating classes", print_supp_op_classes, 1, 255, BIT(PRINT_SCAN), }, +- [66] = { "Measurement Pilot Transmission", print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, +- [74] = { "Overlapping BSS scan params", print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, +- [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, +- [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, +- [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, +- [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, +- [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, +- [50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, +- [70] = { "RM enabled capabilities", print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, +- [113] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, +- [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, +- [127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), }, +- [107] = { "802.11u Interworking", print_interworking, 0, 255, BIT(PRINT_SCAN), }, +- [108] = { "802.11u Advertisement", print_11u_advert, 0, 255, BIT(PRINT_SCAN), }, +- [111] = { "802.11u Roaming Consortium", print_11u_rcon, 2, 255, BIT(PRINT_SCAN), }, +- [195] = { "Transmit Power Envelope", print_tx_power_envelope, 2, 5, BIT(PRINT_SCAN), }, +- [214] = { "Short beacon interval", print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), }, +- [217] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), }, +- [232] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), }, ++ [EID_SSID] = { "SSID", print_ssid, 0, 32, ++ BIT(PRINT_SCAN) | BIT(PRINT_LINK) | BIT(PRINT_LINK_MLO_MLD), }, ++ [EID_SUPP_RATES] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, ++ [EID_DS_PARAMS] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, ++ [EID_TIM] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, ++ [EID_IBSS_TIM_PARAMS] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), }, ++ [EID_COUNTRY] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), }, ++ [EID_BSS_LOAD] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, ++ [EID_POWER_CONSTRAINT] = { "Power constraint", print_powerconstraint, ++ 1, 1, BIT(PRINT_SCAN), }, ++ [EID_TPC_REPORT] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, ++ [EID_ERP_INFO] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_HT_CAPABILITY] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, ++ [EID_ERP_D4_0] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_AP_CHAN_REPORT] = { "AP Channel Report", print_ap_channel_report, ++ 1, 255, BIT(PRINT_SCAN), }, ++ [EID_SUPP_OP_CLASSES] = { "Supported operating classes", ++ print_supp_op_classes, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_MEASUREMENT_PILOT_TX] = { "Measurement Pilot Transmission", ++ print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_OVERLAP_BSS_SCAN_PARAM] = { "Overlapping BSS scan params", ++ print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, ++ [EID_HT_OPERATION] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, ++ [EID_SECONDARY_CH_OFFSET] = { "Secondary Channel Offset", ++ print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, ++ [EID_VHT_CAPABILITY] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, ++ [EID_VHT_OPERATION] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, ++ [EID_RSN] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, ++ [EID_EXT_SUPP_RATES] = { "Extended supported rates", print_supprates, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_RM_ENABLED_CAPABILITIES] = { "RM enabled capabilities", ++ print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, ++ [EID_MESH_CONFIG] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, ++ [EID_MESH_ID] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, ++ [EID_EXT_CAPABILITY] = { "Extended capabilities", print_capabilities, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_INTERWORKING] = { "802.11u Interworking", print_interworking, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_ADVERTISEMENT] = { "802.11u Advertisement", print_11u_advert, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_ROAMING_CONSORTIUM] = { "802.11u Roaming Consortium", ++ print_11u_rcon, 2, 255, BIT(PRINT_SCAN), }, ++ [EID_TRANSMIT_POWER_ENVELOPE] = { "Transmit Power Envelope", ++ print_tx_power_envelope, 2, 5, BIT(PRINT_SCAN), }, ++ [EID_SHORT_BEACON_INTERVAL] = { "Short beacon interval", ++ print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), }, ++ [EID_S1G_CAPABILITY] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), }, ++ [EID_S1G_OPERATION] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), }, + }; + + static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data, +@@ -2392,8 +2406,8 @@ static void print_he_oper(const uint8_t + } + + static const struct ie_print ext_printers[] = { +- [35] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, +- [36] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, ++ [EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, ++ [EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, + }; + + static void print_extension(unsigned char len, unsigned char *ie, diff --git a/package/network/utils/iw/patches/104-iw-scan-replace-passed-ie-buffer-with-ie-context.patch b/package/network/utils/iw/patches/104-iw-scan-replace-passed-ie-buffer-with-ie-context.patch new file mode 100644 index 0000000000..aa8b8b16a0 --- /dev/null +++ b/package/network/utils/iw/patches/104-iw-scan-replace-passed-ie-buffer-with-ie-context.patch @@ -0,0 +1,482 @@ +From a0a7ddef29fc412cee7e3ca027905218b145a40f Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Fri, 22 Nov 2024 08:18:51 -0800 +Subject: [PATCH] iw: scan: replace passed ie buffer with ie context + +Since some ies require references to other ies, parse +the ie list once before to create a context and prevent +parsing more than the two times required. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20241122161851.647214-1-dylan.eskew@candelatech.com +[cleanups] +Signed-off-by: Johannes Berg +--- + scan.c | 141 +++++++++++++++++++++++++++++++-------------------------- + 1 file changed, 76 insertions(+), 65 deletions(-) + +--- a/scan.c ++++ b/scan.c +@@ -554,13 +554,12 @@ static void tab_on_first(bool *first) + *first = false; + } + +-struct print_ies_data { +- unsigned char *ie; +- int ielen; ++struct ie_context { ++ bool is_vht_cap; + }; + + static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" "); + print_ssid_escaped(len, data); +@@ -572,7 +571,7 @@ static void print_ssid(const uint8_t typ + + static void print_supprates(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i; + +@@ -595,7 +594,7 @@ static void print_supprates(const uint8_ + + static void print_rm_enabled_capabilities(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + __u64 capa = ((__u64) data[0]) | + ((__u64) data[1]) << 8 | +@@ -649,7 +648,7 @@ static void print_rm_enabled_capabilitie + } + + static void print_ds(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" channel %d\n", data[0]); + } +@@ -669,7 +668,7 @@ static const char *country_env_str(char + } + + static void print_country(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %.*s", 2, data); + +@@ -716,21 +715,21 @@ static void print_country(const uint8_t + + static void print_powerconstraint(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %d dB\n", data[0]); + } + + static void print_tpcreport(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" TX power: %d dBm\n", data[0]); + /* printf(" Link Margin (%d dB) is reserved in Beacons\n", data[1]); */ + } + + static void print_erp(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + if (data[0] == 0x00) + printf(" "); +@@ -744,7 +743,7 @@ static void print_erp(const uint8_t type + } + + static void print_ap_channel_report(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + uint8_t oper_class = data[0]; + int i; +@@ -1084,13 +1083,13 @@ static void print_osen_ie(const char *de + } + + static void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + print_rsn_ie("CCMP", "IEEE 802.1X", len, data); + } + + static void print_ht_capa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_ht_capability(data[0] | (data[1] << 8)); +@@ -1135,7 +1134,7 @@ static const char* vgroup_11u(uint8_t t) + + static void print_interworking(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* See Section 7.3.2.92 in the 802.11u spec. */ + printf("\n"); +@@ -1168,7 +1167,7 @@ static void print_interworking(const uin + + static void print_11u_advert(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* See Section 7.3.2.93 in the 802.11u spec. */ + /* TODO: This code below does not decode private protocol IDs */ +@@ -1201,7 +1200,7 @@ static void print_11u_advert(const uint8 + } + + static void print_11u_rcon(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* See Section 7.3.2.96 in the 802.11u spec. */ + int idx = 0; +@@ -1254,7 +1253,7 @@ static void print_11u_rcon(const uint8_t + + static void print_tx_power_envelope(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + const uint8_t local_max_tx_power_count = data[0] & 7; + const uint8_t local_max_tx_power_unit_interp = (data[0] >> 3) & 7; +@@ -1290,7 +1289,7 @@ static const char *ht_secondary_offset[4 + }; + + static void print_ht_op(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + static const char *protection[4] = { + "no", +@@ -1322,21 +1321,10 @@ static void print_ht_op(const uint8_t ty + + static void print_capabilities(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i, base, bit, si_duration = 0, max_amsdu = 0; +- bool s_psmp_support = false, is_vht_cap = false; +- unsigned char *ie = ie_buffer->ie; +- int ielen = ie_buffer->ielen; +- +- while (ielen >= 2 && ielen >= ie[1]) { +- if (ie[0] == 191) { +- is_vht_cap = true; +- break; +- } +- ielen -= ie[1] + 2; +- ie += ie[1] + 2; +- } ++ bool s_psmp_support = false; + + for (i = 0; i < len; i++) { + base = i * 8; +@@ -1432,8 +1420,8 @@ static void print_capabilities(const uin + CAPA(61, "TDLS Wider Bandwidth"); + CAPA(62, "Operating Mode Notification"); + +- ADD_BIT_VAL(63, is_vht_cap, max_amsdu, 1); +- ADD_BIT_VAL(64, is_vht_cap, max_amsdu, 2); ++ ADD_BIT_VAL(63, ctx->is_vht_cap, max_amsdu, 1); ++ ADD_BIT_VAL(64, ctx->is_vht_cap, max_amsdu, 2); + + CAPA(65, "Channel Schedule Management"); + CAPA(66, "Geodatabase Inband Enabling Signal"); +@@ -1462,7 +1450,7 @@ static void print_capabilities(const uin + printf("\n\t\t * Service Interval Granularity is %d ms", + (si_duration + 1) * 5); + +- if (is_vht_cap) { ++ if (ctx->is_vht_cap) { + printf("\n\t\t * Max Number Of MSDUs In A-MSDU is "); + switch (max_amsdu) { + case 0: +@@ -1486,7 +1474,7 @@ static void print_capabilities(const uin + } + + static void print_tim(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" DTIM Count %u DTIM Period %u Bitmap Control 0x%x " + "Bitmap[0] 0x%x", +@@ -1497,13 +1485,13 @@ static void print_tim(const uint8_t type + } + + static void print_ibssatim(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %d TUs\n", (data[1] << 8) + data[0]); + } + + static void print_vht_capa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_vht_info((__u32) data[0] | ((__u32)data[1] << 8) | +@@ -1512,7 +1500,7 @@ static void print_vht_capa(const uint8_t + } + + static void print_vht_oper(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + const char *chandwidths[] = { + [0] = "20 or 40 MHz", +@@ -1531,7 +1519,7 @@ static void print_vht_oper(const uint8_t + + static void print_supp_op_classes(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + uint8_t *p = (uint8_t*) data; + const uint8_t *next_data = p + len; +@@ -1565,7 +1553,7 @@ static void print_supp_op_classes(const + + static void print_measurement_pilot_tx(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + uint8_t *p, len_remaining; + +@@ -1614,7 +1602,7 @@ static void print_measurement_pilot_tx(c + + static void print_obss_scan_params(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + printf("\t\t * passive dwell: %d TUs\n", (data[1] << 8) | data[0]); +@@ -1629,7 +1617,7 @@ static void print_obss_scan_params(const + + static void print_secchan_offs(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + if (data[0] < ARRAY_SIZE(ht_secondary_offset)) + printf(" %s (%d)\n", ht_secondary_offset[data[0]], data[0]); +@@ -1638,7 +1626,7 @@ static void print_secchan_offs(const uin + } + + static void print_bss_load(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + printf("\t\t * station count: %d\n", (data[1] << 8) | data[0]); +@@ -1648,7 +1636,7 @@ static void print_bss_load(const uint8_t + + static void print_mesh_conf(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + printf("\t\t * Active Path Selection Protocol ID: %d\n", data[0]); +@@ -1681,7 +1669,7 @@ static void print_mesh_conf(const uint8_ + + static void print_s1g_capa(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_s1g_capability(data); +@@ -1689,14 +1677,14 @@ static void print_s1g_capa(const uint8_t + + static void print_short_beacon_int(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %d\n", (data[1] << 8) | data[0]); + } + + static void print_s1g_oper(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int oper_ch_width, prim_ch_width; + int prim_ch_width_subfield = data[0] & 0x1; +@@ -1777,14 +1765,14 @@ static void print_s1g_oper(const uint8_t + struct ie_print { + const char *name; + void (*print)(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer); ++ const struct ie_context *ctx); + uint8_t minlen, maxlen; + uint8_t flags; + }; + + static void print_ie(const struct ie_print *p, const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i; + +@@ -1805,7 +1793,7 @@ static void print_ie(const struct ie_pri + return; + } + +- p->print(type, len, data, ie_buffer); ++ p->print(type, len, data, ctx); + } + + #define PRINT_IGN { \ +@@ -1867,14 +1855,14 @@ static const struct ie_print ieprinters[ + }; + + static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + print_rsn_ie("TKIP", "IEEE 802.1X", len, data); + } + + static void print_wifi_osen(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + print_osen_ie("OSEN", "OSEN", len, data); + } +@@ -1922,7 +1910,7 @@ static bool print_wifi_wmm_param(const u + } + + static void print_wifi_wmm(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i; + +@@ -1965,7 +1953,7 @@ static const char * wifi_wps_dev_passwd_ + } + + static void print_wifi_wps(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + bool first = true; + __u16 subtype, sublen; +@@ -2205,7 +2193,7 @@ static const struct ie_print wifiprinter + + static inline void print_p2p(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + bool first = true; + __u8 subtype; +@@ -2287,7 +2275,7 @@ static inline void print_p2p(const uint8 + + static inline void print_hs20_ind(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* I can't find the spec for this...just going off what wireshark uses. */ + printf("\n"); +@@ -2299,7 +2287,7 @@ static inline void print_hs20_ind(const + + static void print_wifi_owe_tarns(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + char mac_addr[20]; + int ssid_len; +@@ -2392,14 +2380,14 @@ static void print_vendor(unsigned char l + } + + static void print_he_capa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_he_capability(data, len); + } + + static void print_he_oper(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_he_operation(data, len); +@@ -2437,23 +2425,46 @@ static void print_extension(unsigned cha + } + } + ++static void init_context(struct ie_context *ctx, ++ unsigned char *ie, int ielen) ++{ ++ unsigned char *pos = ie; ++ int remaining = ielen; ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ ++ if (!ie || !ielen) ++ return; ++ ++ while (remaining >= 2 && remaining - 2 >= pos[1]) { ++ switch (pos[0]) { ++ case EID_VHT_CAPABILITY: ++ ctx->is_vht_cap = true; ++ break; ++ } ++ ++ remaining -= pos[1] + 2; ++ pos += pos[1] + 2; ++ } ++} ++ + void print_ies(unsigned char *ie, int ielen, bool unknown, + enum print_ie_type ptype) + { +- struct print_ies_data ie_buffer = { +- .ie = ie, +- .ielen = ielen }; ++ struct ie_context ctx; + +- if (ie == NULL || ielen < 0) ++ if (!ie) + return; + ++ init_context(&ctx, ie, ielen); ++ + while (ielen >= 2 && ielen - 2 >= ie[1]) { + if (ie[0] < ARRAY_SIZE(ieprinters) && + ieprinters[ie[0]].name && + ieprinters[ie[0]].flags & BIT(ptype) && + ie[1] > 0) { + print_ie(&ieprinters[ie[0]], +- ie[0], ie[1], ie + 2, &ie_buffer); ++ ie[0], ie[1], ie + 2, &ctx); + } else if (ie[0] == 221 /* vendor */) { + print_vendor(ie[1], ie + 2, unknown, ptype); + } else if (ie[0] == 255 /* extension */) { diff --git a/package/network/utils/iw/patches/105-iw-util-update-and-clean-up-eht-capa-printing.patch b/package/network/utils/iw/patches/105-iw-util-update-and-clean-up-eht-capa-printing.patch new file mode 100644 index 0000000000..3970677d74 --- /dev/null +++ b/package/network/utils/iw/patches/105-iw-util-update-and-clean-up-eht-capa-printing.patch @@ -0,0 +1,207 @@ +From 4c859917316b69e66ba241d85b4da6ee01292a11 Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Wed, 19 Mar 2025 11:39:17 -0700 +Subject: [PATCH] iw: util: update and clean up eht capa printing + +A number of fields were either missing or incorrect, so +update to more aligned with 802.11be spec. Also clean up +printout formatting. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20250319183918.1215853-2-dylan.eskew@candelatech.com +Signed-off-by: Johannes Berg +--- + iw.h | 2 + + util.c | 124 ++++++++++++++++++++++++++++++++++++++++++++------------- + 2 files changed, 99 insertions(+), 27 deletions(-) + +--- a/iw.h ++++ b/iw.h +@@ -224,6 +224,8 @@ void print_vht_info(__u32 capa, const __ + void print_he_capability(const uint8_t *ie, int len); + void print_he_operation(const uint8_t *ie, int len); + void print_he_info(struct nlattr *nl_iftype); ++void print_eht_capability(const uint8_t *ie, int len, const uint8_t *he_cap, ++ bool from_ap); + void print_eht_info(struct nlattr *nl_iftype, int band); + void print_s1g_capability(const uint8_t *caps); + +--- a/util.c ++++ b/util.c +@@ -1515,11 +1515,11 @@ static void __print_eht_capa(int band, + const __u8 *mcs_set, size_t mcs_len, + const __u8 *ppet, size_t ppet_len, + const __u16 *he_phy_cap, ++ bool from_ap, + bool indent) + { + unsigned int i; + const char *pre = indent ? "\t" : ""; +- const char *mcs[] = { "0-7", "8-9", "10-11", "12-13"}; + + #define PRINT_EHT_CAP(_var, _idx, _bit, _str) \ + do { \ +@@ -1534,6 +1534,7 @@ static void __print_eht_capa(int band, + } while (0) + + #define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__) ++ #define PRINT_EHT_MAC_CAP_MASK(...) PRINT_EHT_CAP_MASK(mac_cap, __VA_ARGS__) + #define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__) + #define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__) + +@@ -1542,13 +1543,22 @@ static void __print_eht_capa(int band, + printf("%02x", mac_cap[i]); + printf("):\n"); + +- PRINT_EHT_MAC_CAP(0, 0, "NSEP priority access Supported"); ++ PRINT_EHT_MAC_CAP(0, 0, "EPCS Priority Access Supported"); + PRINT_EHT_MAC_CAP(0, 1, "EHT OM Control Supported"); +- PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Supported"); +- PRINT_EHT_MAC_CAP(0, 3, "ARR Supported"); ++ PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Mode 1 Supported"); ++ PRINT_EHT_MAC_CAP(0, 3, "Triggered TXOP Sharing Mode 2 Supported"); ++ PRINT_EHT_MAC_CAP(0, 4, "Restricted TWP Supported"); ++ PRINT_EHT_MAC_CAP(0, 5, "SCS Traffic Description Supported"); ++ PRINT_EHT_MAC_CAP_MASK(0, 6, 0x3, "Maximum MPDU Length"); ++ ++ PRINT_EHT_MAC_CAP(1, 1, "Maximum A_MPDU Length Exponent Extension"); ++ PRINT_EHT_MAC_CAP(1, 2, "EHT TRS Supported"); ++ PRINT_EHT_MAC_CAP(1, 3, "TXOP Return In TXOP Sharing Mode 2 Supported"); ++ PRINT_EHT_MAC_CAP(1, 4, "Two BQRs Supported"); ++ PRINT_EHT_MAC_CAP_MASK(1, 5, 0x3, "EHT Link Adaptation Supported"); + +- printf("%s\t\tEHT PHY Capabilities: (0x", pre); +- for (i = 0; i < 8; i++) ++ printf("%s\t\tEHT PHY Capabilities (0x", pre); ++ for (i = 0; i < 9; i++) + printf("%02x", ((__u8 *)phy_cap)[i]); + printf("):\n"); + +@@ -1594,39 +1604,77 @@ static void __print_eht_capa(int band, + PRINT_EHT_PHY_CAP(1, 28, "MU Beamformer (80MHz)"); + PRINT_EHT_PHY_CAP(1, 29, "MU Beamformer (160MHz)"); + PRINT_EHT_PHY_CAP(1, 30, "MU Beamformer (320MHz)"); ++ PRINT_EHT_PHY_CAP(1, 31, "TB Sounding Feedback Rate Limit"); + +- printf("%s\t\tEHT MCS/NSS: (0x", pre); +- for (i = 0; i < mcs_len; i++) +- printf("%02x", ((__u8 *)mcs_set)[i]); +- printf("):\n"); ++ PRINT_EHT_PHY_CAP(2, 0, "Rx 1024-QAM In Wider Bandwidth DL OFDMA Supported"); ++ PRINT_EHT_PHY_CAP(2, 1, "Rx 4096-QAM In Wider Bandwidth DL OFDMA Supported"); + +- if (!(he_phy_cap[0] & ((BIT(2) | BIT(3) | BIT(4)) << 8))){ +- for (i = 0; i < 4; i++) +- printf("%s\t\tEHT bw=20 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ if (!from_ap && ++ !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8))) { ++ static const char * const mcs[] = { "0-7", "8-9", "10-11", "12-13" }; ++ ++ printf("%s\t\tEHT-MCS Map (20 Mhz Non-AP STA) (0x", pre); ++ for (i = 0; i < mcs_len; i++) ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 4; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } else { +- if (he_phy_cap[0] & (BIT(2) << 8)) { ++ static const char * const mcs[] = { "0-9", "10-11", "12-13"}; ++ ++ /* Bit 1 corresponds to 2.4Ghz 40Mhz support ++ * Bit 2 corresponds to 5/6Ghz 40 and 80Mhz support ++ * If no Channel Width bits are set, but we are an AP, we use ++ * this MCS logic also. ++ */ ++ if (he_phy_cap[0] & ((BIT(1) | BIT(2)) << 8) || ++ (from_ap && !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8)))) { ++ printf("%s\t\tEHT-MCS Map (BW <= 80) (0x", pre); + for (i = 0; i < 3; i++) +- printf("%s\t\tEHT bw <= 80 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i + 1], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 3; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } + mcs_set += 3; + + if (he_phy_cap[0] & (BIT(3) << 8)) { ++ printf("%s\t\tEHT-MCS Map (BW = 160) (0x", pre); + for (i = 0; i < 3; i++) +- printf("%s\t\tEHT bw=160 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i + 1], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 3; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } + + mcs_set += 3; + if (band == NL80211_BAND_6GHZ && (phy_cap[0] & BIT(1))) { ++ printf("%s\t\tEHT-MCS Map (BW = 320) (0x", pre); + for (i = 0; i < 3; i++) +- printf("%s\t\tEHT bw=320 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i + 1], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 3; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } + } + +@@ -1713,7 +1761,29 @@ void print_eht_info(struct nlattr *nl_if + } + + __print_eht_capa(band, mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len, +- he_phy_cap, true); ++ he_phy_cap, false, true); ++} ++ ++void print_eht_capability(const uint8_t *ie, int len, const uint8_t *he_cap, ++ bool from_ap) ++{ ++ const void *mac_cap, *phy_cap, *mcs_set, *he_phy_cap; ++ int mcs_len; ++ int i = 0; ++ ++ mac_cap = &ie[i]; ++ i += 2; ++ ++ phy_cap = &ie[i]; ++ i += 9; ++ ++ mcs_set = &ie[i]; ++ mcs_len = len - i; ++ ++ he_phy_cap = &he_cap[6]; ++ ++ __print_eht_capa(NL80211_BAND_6GHZ, mac_cap, phy_cap, mcs_set, mcs_len, ++ NULL, 0, he_phy_cap - 1, from_ap, false); + } + + void print_he_capability(const uint8_t *ie, int len) diff --git a/package/network/utils/iw/patches/106-iw-scan-add-eht-capability-parsing.patch b/package/network/utils/iw/patches/106-iw-scan-add-eht-capability-parsing.patch new file mode 100644 index 0000000000..ff8a323d34 --- /dev/null +++ b/package/network/utils/iw/patches/106-iw-scan-add-eht-capability-parsing.patch @@ -0,0 +1,175 @@ +From a6ad3f11ead18d1812c7d3759991dc22b20d90da Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Wed, 19 Mar 2025 11:39:18 -0700 +Subject: [PATCH] iw: scan: add eht capability parsing + +Add ability to print out EHT capabilities from +AP beacons. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20250319183918.1215853-3-dylan.eskew@candelatech.com +Signed-off-by: Johannes Berg +--- + ieee80211.h | 1 + + iw.h | 2 +- + link.c | 5 +++-- + scan.c | 34 +++++++++++++++++++++++++++------- + 4 files changed, 32 insertions(+), 10 deletions(-) + +--- a/ieee80211.h ++++ b/ieee80211.h +@@ -99,6 +99,7 @@ enum elem_id { + enum elem_id_ext { + EID_EXT_HE_CAPABILITY = 35, + EID_EXT_HE_OPERATION = 36, ++ EID_EXT_EHT_CAPABILITY = 108, + }; + + #define SUITE(oui, id) (((oui) << 8) | (id)) +--- a/iw.h ++++ b/iw.h +@@ -256,7 +256,7 @@ enum print_ie_type { + #define BIT(x) (1ULL<<(x)) + + void print_ies(unsigned char *ie, int ielen, bool unknown, +- enum print_ie_type ptype); ++ enum print_ie_type ptype, bool from_ap); + + void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen); + void iw_hexdump(const char *prefix, const __u8 *data, size_t len); +--- a/link.c ++++ b/link.c +@@ -93,7 +93,7 @@ static int link_bss_handler(struct nl_ms + if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) + print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), + nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), +- false, PRINT_LINK_MLO_MLD); ++ false, PRINT_LINK_MLO_MLD, false); + } + } else { + memcpy(result->sta_addr, nla_data(bss[NL80211_BSS_BSSID]), 6); +@@ -121,7 +121,8 @@ static int link_bss_handler(struct nl_ms + if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) + print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), + nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), +- false, result->mld ? PRINT_LINK_MLO_LINK : PRINT_LINK); ++ false, result->mld ? PRINT_LINK_MLO_LINK : PRINT_LINK, ++ false); + + if (bss[NL80211_BSS_FREQUENCY_OFFSET]) + freq_offset = nla_get_u32(bss[NL80211_BSS_FREQUENCY_OFFSET]); +--- a/scan.c ++++ b/scan.c +@@ -555,7 +555,9 @@ static void tab_on_first(bool *first) + } + + struct ie_context { ++ bool from_ap; + bool is_vht_cap; ++ const uint8_t *he_cap; + }; + + static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data, +@@ -2393,12 +2395,21 @@ static void print_he_oper(const uint8_t + print_he_operation(data, len); + } + ++static void print_eht_capa(const uint8_t type, uint8_t len, ++ const uint8_t *data, const struct ie_context *ctx) ++{ ++ printf("\n"); ++ print_eht_capability(data, len, ctx->he_cap, ctx->from_ap); ++} ++ + static const struct ie_print ext_printers[] = { + [EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, + [EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, ++ [EID_EXT_EHT_CAPABILITY] = { "EHT capabilities", print_eht_capa, 13, 30, BIT(PRINT_SCAN), }, + }; + + static void print_extension(unsigned char len, unsigned char *ie, ++ const struct ie_context *ctx, + bool unknown, enum print_ie_type ptype) + { + unsigned char tag; +@@ -2411,7 +2422,7 @@ static void print_extension(unsigned cha + tag = ie[0]; + if (tag < ARRAY_SIZE(ext_printers) && ext_printers[tag].name && + ext_printers[tag].flags & BIT(ptype)) { +- print_ie(&ext_printers[tag], tag, len - 1, ie + 1, NULL); ++ print_ie(&ext_printers[tag], tag, len - 1, ie + 1, ctx); + return; + } + +@@ -2426,7 +2437,7 @@ static void print_extension(unsigned cha + } + + static void init_context(struct ie_context *ctx, +- unsigned char *ie, int ielen) ++ unsigned char *ie, int ielen, bool from_ap) + { + unsigned char *pos = ie; + int remaining = ielen; +@@ -2436,11 +2447,20 @@ static void init_context(struct ie_conte + if (!ie || !ielen) + return; + ++ ctx->from_ap = from_ap; ++ + while (remaining >= 2 && remaining - 2 >= pos[1]) { + switch (pos[0]) { + case EID_VHT_CAPABILITY: + ctx->is_vht_cap = true; + break; ++ case EID_EXTENSION: ++ switch (pos[2]) { ++ case EID_EXT_HE_CAPABILITY: ++ ctx->he_cap = pos + 3; ++ break; ++ } ++ break; + } + + remaining -= pos[1] + 2; +@@ -2449,14 +2469,14 @@ static void init_context(struct ie_conte + } + + void print_ies(unsigned char *ie, int ielen, bool unknown, +- enum print_ie_type ptype) ++ enum print_ie_type ptype, bool from_ap) + { + struct ie_context ctx; + + if (!ie) + return; + +- init_context(&ctx, ie, ielen); ++ init_context(&ctx, ie, ielen, from_ap); + + while (ielen >= 2 && ielen - 2 >= ie[1]) { + if (ie[0] < ARRAY_SIZE(ieprinters) && +@@ -2468,7 +2488,7 @@ void print_ies(unsigned char *ie, int ie + } else if (ie[0] == 221 /* vendor */) { + print_vendor(ie[1], ie + 2, unknown, ptype); + } else if (ie[0] == 255 /* extension */) { +- print_extension(ie[1], ie + 2, unknown, ptype); ++ print_extension(ie[1], ie + 2, &ctx, unknown, ptype); + } else if (unknown) { + int i; + +@@ -2673,13 +2693,13 @@ static int print_bss_handler(struct nl_m + printf("\tInformation elements from Probe Response " + "frame:\n"); + print_ies(nla_data(ies), nla_len(ies), +- params->unknown, params->type); ++ params->unknown, params->type, true); + } + if (bss[NL80211_BSS_BEACON_IES] && show--) { + printf("\tInformation elements from Beacon frame:\n"); + print_ies(nla_data(bss[NL80211_BSS_BEACON_IES]), + nla_len(bss[NL80211_BSS_BEACON_IES]), +- params->unknown, params->type); ++ params->unknown, params->type, true); + } + + return NL_SKIP; diff --git a/package/network/utils/iw/patches/107-iw-fix-EHT-capabilities-on-Big-Endian-platforms.patch b/package/network/utils/iw/patches/107-iw-fix-EHT-capabilities-on-Big-Endian-platforms.patch new file mode 100644 index 0000000000..d0f15eaec5 --- /dev/null +++ b/package/network/utils/iw/patches/107-iw-fix-EHT-capabilities-on-Big-Endian-platforms.patch @@ -0,0 +1,107 @@ +From 59660a349cf35903e951f99bdd8a74df063c912e Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Fri, 2 May 2025 21:44:05 +0200 +Subject: [PATCH] iw: fix EHT capabilities on Big Endian platforms + +IE fields are encoded in Little Endian and are not correctly +printed on Big Endian platforms. + +Fixes: 5a71b722270c ("iw: Print local EHT capabilities") +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250502194405.3489240-1-olek2@wp.pl +Signed-off-by: Johannes Berg +--- + util.c | 40 +++++++++++++++++++++++++--------------- + 1 file changed, 25 insertions(+), 15 deletions(-) + +--- a/util.c ++++ b/util.c +@@ -1521,22 +1521,31 @@ static void __print_eht_capa(int band, + unsigned int i; + const char *pre = indent ? "\t" : ""; + +- #define PRINT_EHT_CAP(_var, _idx, _bit, _str) \ ++ #define PRINT_EHT_MAC_CAP(_idx, _bit, _str) \ + do { \ +- if (_var[_idx] & BIT(_bit)) \ ++ if (mac_cap[_idx] & BIT(_bit)) \ + printf("%s\t\t\t" _str "\n", pre); \ + } while (0) + +- #define PRINT_EHT_CAP_MASK(_var, _idx, _shift, _mask, _str) \ ++ #define PRINT_EHT_MAC_CAP_MASK(_idx, _shift, _mask, _str) \ + do { \ +- if ((_var[_idx] >> _shift) & _mask) \ +- printf("%s\t\t\t" _str ": %d\n", pre, (_var[_idx] >> _shift) & _mask); \ ++ if ((mac_cap[_idx] >> _shift) & _mask) \ ++ printf("%s\t\t\t" _str ": %d\n", pre, \ ++ (mac_cap[_idx] >> _shift) & _mask); \ + } while (0) + +- #define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__) +- #define PRINT_EHT_MAC_CAP_MASK(...) PRINT_EHT_CAP_MASK(mac_cap, __VA_ARGS__) +- #define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__) +- #define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__) ++ #define PRINT_EHT_PHY_CAP(_idx, _bit, _str) \ ++ do { \ ++ if (le32toh(phy_cap[_idx]) & BIT(_bit)) \ ++ printf("%s\t\t\t" _str "\n", pre); \ ++ } while (0) ++ ++ #define PRINT_EHT_PHY_CAP_MASK(_idx, _shift, _mask, _str) \ ++ do { \ ++ if ((le32toh(phy_cap[_idx]) >> _shift) & _mask) \ ++ printf("%s\t\t\t" _str ": %d\n", pre, \ ++ (le32toh(phy_cap[_idx]) >> _shift) & _mask); \ ++ } while (0) + + printf("%s\t\tEHT MAC Capabilities (0x", pre); + for (i = 0; i < 2; i++) +@@ -1610,7 +1619,7 @@ static void __print_eht_capa(int band, + PRINT_EHT_PHY_CAP(2, 1, "Rx 4096-QAM In Wider Bandwidth DL OFDMA Supported"); + + if (!from_ap && +- !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8))) { ++ !(le16toh(he_phy_cap[0]) & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8))) { + static const char * const mcs[] = { "0-7", "8-9", "10-11", "12-13" }; + + printf("%s\t\tEHT-MCS Map (20 Mhz Non-AP STA) (0x", pre); +@@ -1632,8 +1641,9 @@ static void __print_eht_capa(int band, + * If no Channel Width bits are set, but we are an AP, we use + * this MCS logic also. + */ +- if (he_phy_cap[0] & ((BIT(1) | BIT(2)) << 8) || +- (from_ap && !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8)))) { ++ if (le16toh(he_phy_cap[0]) & ((BIT(1) | BIT(2)) << 8) || ++ (from_ap && !(le16toh(he_phy_cap[0]) & ++ ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8)))) { + printf("%s\t\tEHT-MCS Map (BW <= 80) (0x", pre); + for (i = 0; i < 3; i++) + printf("%02x", ((__u8 *)mcs_set)[i]); +@@ -1648,7 +1658,7 @@ static void __print_eht_capa(int band, + } + mcs_set += 3; + +- if (he_phy_cap[0] & (BIT(3) << 8)) { ++ if (le16toh(he_phy_cap[0]) & (BIT(3) << 8)) { + printf("%s\t\tEHT-MCS Map (BW = 160) (0x", pre); + for (i = 0; i < 3; i++) + printf("%02x", ((__u8 *)mcs_set)[i]); +@@ -1663,7 +1673,7 @@ static void __print_eht_capa(int band, + } + + mcs_set += 3; +- if (band == NL80211_BAND_6GHZ && (phy_cap[0] & BIT(1))) { ++ if (band == NL80211_BAND_6GHZ && (le32toh(phy_cap[0]) & BIT(1))) { + printf("%s\t\tEHT-MCS Map (BW = 320) (0x", pre); + for (i = 0; i < 3; i++) + printf("%02x", ((__u8 *)mcs_set)[i]); +@@ -1678,7 +1688,7 @@ static void __print_eht_capa(int band, + } + } + +- if (ppet && ppet_len && (phy_cap[1] & BIT(11))) { ++ if (ppet && ppet_len && (le32toh(phy_cap[1]) & BIT(11))) { + printf("%s\t\tEHT PPE Thresholds ", pre); + for (i = 0; i < ppet_len; i++) + if (ppet[i]) diff --git a/package/network/utils/iw/patches/108-iw-scan-Add-printing-of-EHT-Operation-Element.patch b/package/network/utils/iw/patches/108-iw-scan-Add-printing-of-EHT-Operation-Element.patch new file mode 100644 index 0000000000..81b1def031 --- /dev/null +++ b/package/network/utils/iw/patches/108-iw-scan-Add-printing-of-EHT-Operation-Element.patch @@ -0,0 +1,131 @@ +From 8ea80d378ce5f727e69493533a666278c6a568a7 Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Fri, 2 May 2025 12:03:53 +0200 +Subject: [PATCH] iw: scan: Add printing of EHT Operation Element + +Add ability to print out EHT capabilities from AP beacons. + +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250502100353.3149470-1-olek2@wp.pl +[add default case to bandwidth switch] +Signed-off-by: Johannes Berg +--- + ieee80211.h | 1 + + iw.h | 1 + + scan.c | 8 +++++++ + util.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 73 insertions(+) + +--- a/ieee80211.h ++++ b/ieee80211.h +@@ -99,6 +99,7 @@ enum elem_id { + enum elem_id_ext { + EID_EXT_HE_CAPABILITY = 35, + EID_EXT_HE_OPERATION = 36, ++ EID_EXT_EHT_OPERATION = 106, + EID_EXT_EHT_CAPABILITY = 108, + }; + +--- a/iw.h ++++ b/iw.h +@@ -226,6 +226,7 @@ void print_he_operation(const uint8_t *i + void print_he_info(struct nlattr *nl_iftype); + void print_eht_capability(const uint8_t *ie, int len, const uint8_t *he_cap, + bool from_ap); ++void print_eht_operation(const uint8_t *ie, int len); + void print_eht_info(struct nlattr *nl_iftype, int band); + void print_s1g_capability(const uint8_t *caps); + +--- a/scan.c ++++ b/scan.c +@@ -2402,10 +2402,18 @@ static void print_eht_capa(const uint8_t + print_eht_capability(data, len, ctx->he_cap, ctx->from_ap); + } + ++static void print_eht_oper(const uint8_t type, uint8_t len, const uint8_t *data, ++ const struct ie_context *ctx) ++{ ++ printf("\n"); ++ print_eht_operation(data, len); ++} ++ + static const struct ie_print ext_printers[] = { + [EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, + [EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, + [EID_EXT_EHT_CAPABILITY] = { "EHT capabilities", print_eht_capa, 13, 30, BIT(PRINT_SCAN), }, ++ [EID_EXT_EHT_OPERATION] = { "EHT Operation", print_eht_oper, 5, 10, BIT(PRINT_SCAN), }, + }; + + static void print_extension(unsigned char len, unsigned char *ie, +--- a/util.c ++++ b/util.c +@@ -1917,6 +1917,69 @@ void print_he_operation(const uint8_t *i + } + } + ++void print_eht_operation(const uint8_t *ie, int len) ++{ ++ uint8_t oper_parameters = ie[0]; ++ uint8_t disabled_subchannel_info_present = oper_parameters & 0x02; ++ uint8_t eht_operation_info_present = oper_parameters & 0x01; ++ ++ printf("\t\tEHT Operation Parameters: (0x%02x)\n", ++ oper_parameters); ++ ++ if (oper_parameters & 0x04) ++ printf("\t\t\tEHT Default PE Duration\n"); ++ ++ if (oper_parameters & 0x08) ++ printf("\t\t\tGroup Addressed BU Indication Limit\n"); ++ ++ printf("\t\t\tGroup Addressed BU Indication Exponent: 0x%01x\n", ++ (oper_parameters >> 4 & 3)); ++ ++ printf("\t\tBasic EHT-MCS And Nss Set: 0x"); ++ for (uint8_t i = 0; i < 4; i++) ++ printf("%02x", ie[1 + i]); ++ ++ printf("\n"); ++ ++ if (eht_operation_info_present) { ++ uint8_t offset = 5; ++ const uint8_t control = ie[offset]; ++ uint8_t eht_operation_info_len = 3; ++ ++ if (disabled_subchannel_info_present) ++ eht_operation_info_len += 2; ++ ++ if (len - offset < eht_operation_info_len) { ++ printf("\t\tEHT Operation Info: Invalid\n"); ++ return; ++ } ++ ++ printf("\t\tEHT Operation Info: 0x"); ++ for (uint8_t i = 0; i < eht_operation_info_len; i++) ++ printf("%02x", ie[offset + i]); ++ ++ printf("\n"); ++ printf("\t\t\tChannel Width: "); ++ switch (control & 0x7) { ++ case 0: printf("20 MHz\n"); break; ++ case 1: printf("40 MHz\n"); break; ++ case 2: printf("80 MHz\n"); break; ++ case 3: printf("160 MHz\n"); break; ++ case 4: printf("320 MHz\n"); break; ++ default: printf("invalid bandwidth (%d)\n", control & 0x7); break; ++ } ++ ++ printf("\t\t\tCenter Frequency Segment 0: %hhu\n", ++ ie[offset + 1]); ++ printf("\t\t\tCenter Frequency Segment 1: %hhu\n", ++ ie[offset + 2]); ++ ++ if (disabled_subchannel_info_present) ++ printf("\t\t\tDisabled Subchannel Bitmap: 0x%02x%02x\n", ++ ie[offset + 3], ie[offset + 4]); ++ } ++} ++ + void iw_hexdump(const char *prefix, const __u8 *buf, size_t size) + { + size_t i; diff --git a/package/network/utils/iw/patches/200-reduce_size.patch b/package/network/utils/iw/patches/200-reduce_size.patch index dc1cce99a2..40ca57209d 100644 --- a/package/network/utils/iw/patches/200-reduce_size.patch +++ b/package/network/utils/iw/patches/200-reduce_size.patch @@ -132,7 +132,7 @@ { --- a/scan.c +++ b/scan.c -@@ -1308,6 +1308,9 @@ static void print_ht_op(const uint8_t ty +@@ -1309,6 +1309,9 @@ static void print_ht_op(const uint8_t ty printf("\t\t * secondary channel offset: %s\n", ht_secondary_offset[data[1] & 0x3]); printf("\t\t * STA channel width: %s\n", sta_chan_width[(data[1] & 0x4)>>2]); @@ -142,55 +142,62 @@ printf("\t\t * RIFS: %d\n", (data[1] & 0x8)>>3); printf("\t\t * HT protection: %s\n", protection[data[2] & 0x3]); printf("\t\t * non-GF present: %d\n", (data[2] & 0x4) >> 2); -@@ -1818,30 +1821,31 @@ static void print_ie(const struct ie_pri +@@ -1808,17 +1811,25 @@ static void print_ie(const struct ie_pri static const struct ie_print ieprinters[] = { - [0] = { "SSID", print_ssid, 0, 32, - BIT(PRINT_SCAN) | BIT(PRINT_LINK) | BIT(PRINT_LINK_MLO_MLD), }, -+ [11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, -+ [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, -+ [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, -+ [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, -+ [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, -+ [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, -+ [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, -+ [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, + [EID_SSID] = { "SSID", print_ssid, 0, 32, + BIT(PRINT_SCAN) | BIT(PRINT_LINK) | BIT(PRINT_LINK_MLO_MLD), }, ++ [EID_BSS_LOAD] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, ++ [EID_HT_CAPABILITY] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, ++ [EID_RSN] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, ++ [EID_HT_OPERATION] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, ++ [EID_SECONDARY_CH_OFFSET] = { "Secondary Channel Offset", ++ print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, ++ [EID_MESH_ID] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, ++ [EID_VHT_CAPABILITY] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, ++ [EID_VHT_OPERATION] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, +#ifdef IW_FULL - [1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, - [3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, - [5] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, - [6] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), }, - [7] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), }, -- [11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, - [32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), }, - [35] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, - [42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, -- [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, - [47] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, - [51] = { "AP Channel Report", print_ap_channel_report, 1, 255, BIT(PRINT_SCAN), }, - [59] = { "Supported operating classes", print_supp_op_classes, 1, 255, BIT(PRINT_SCAN), }, - [66] = { "Measurement Pilot Transmission", print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, - [74] = { "Overlapping BSS scan params", print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, -- [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, -- [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, -- [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, -- [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, -- [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, - [50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, - [70] = { "RM enabled capabilities", print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, - [113] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, -- [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, - [127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), }, - [107] = { "802.11u Interworking", print_interworking, 0, 255, BIT(PRINT_SCAN), }, - [108] = { "802.11u Advertisement", print_11u_advert, 0, 255, BIT(PRINT_SCAN), }, -@@ -1850,6 +1854,7 @@ static const struct ie_print ieprinters[ - [214] = { "Short beacon interval", print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), }, - [217] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), }, - [232] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), }, + [EID_SUPP_RATES] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, + [EID_DS_PARAMS] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, + [EID_TIM] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, + [EID_IBSS_TIM_PARAMS] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), }, + [EID_COUNTRY] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), }, +- [EID_BSS_LOAD] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, + [EID_POWER_CONSTRAINT] = { "Power constraint", print_powerconstraint, + 1, 1, BIT(PRINT_SCAN), }, + [EID_TPC_REPORT] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, + [EID_ERP_INFO] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, +- [EID_HT_CAPABILITY] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, + [EID_ERP_D4_0] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, + [EID_AP_CHAN_REPORT] = { "AP Channel Report", print_ap_channel_report, + 1, 255, BIT(PRINT_SCAN), }, +@@ -1828,18 +1839,11 @@ static const struct ie_print ieprinters[ + print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, + [EID_OVERLAP_BSS_SCAN_PARAM] = { "Overlapping BSS scan params", + print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, +- [EID_HT_OPERATION] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, +- [EID_SECONDARY_CH_OFFSET] = { "Secondary Channel Offset", +- print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, +- [EID_VHT_CAPABILITY] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, +- [EID_VHT_OPERATION] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, +- [EID_RSN] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, + [EID_EXT_SUPP_RATES] = { "Extended supported rates", print_supprates, + 0, 255, BIT(PRINT_SCAN), }, + [EID_RM_ENABLED_CAPABILITIES] = { "RM enabled capabilities", + print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, + [EID_MESH_CONFIG] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, +- [EID_MESH_ID] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, + [EID_EXT_CAPABILITY] = { "Extended capabilities", print_capabilities, + 0, 255, BIT(PRINT_SCAN), }, + [EID_INTERWORKING] = { "802.11u Interworking", print_interworking, +@@ -1854,6 +1858,7 @@ static const struct ie_print ieprinters[ + print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), }, + [EID_S1G_CAPABILITY] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), }, + [EID_S1G_OPERATION] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), }, +#endif }; static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data, -@@ -2185,8 +2190,10 @@ static void print_wifi_wps(const uint8_t +@@ -2189,8 +2194,10 @@ static void print_wifi_wps(const uint8_t static const struct ie_print wifiprinters[] = { [1] = { "WPA", print_wifi_wpa, 2, 255, BIT(PRINT_SCAN), }, @@ -201,7 +208,7 @@ }; static inline void print_p2p(const uint8_t type, uint8_t len, -@@ -2349,6 +2356,10 @@ static void print_vendor(unsigned char l +@@ -2353,6 +2360,10 @@ static void print_vendor(unsigned char l return; } @@ -212,7 +219,7 @@ if (len >= 4 && memcmp(data, wfa_oui, 3) == 0) { if (data[3] < ARRAY_SIZE(wfa_printers) && wfa_printers[data[3]].name && -@@ -2491,6 +2502,7 @@ static void print_capa_non_dmg(__u16 cap +@@ -2544,6 +2555,7 @@ static void print_capa_non_dmg(__u16 cap printf(" ESS"); if (capa & WLAN_CAPABILITY_IBSS) printf(" IBSS"); @@ -220,7 +227,7 @@ if (capa & WLAN_CAPABILITY_CF_POLLABLE) printf(" CfPollable"); if (capa & WLAN_CAPABILITY_CF_POLL_REQUEST) -@@ -2519,6 +2531,7 @@ static void print_capa_non_dmg(__u16 cap +@@ -2572,6 +2584,7 @@ static void print_capa_non_dmg(__u16 cap printf(" DelayedBACK"); if (capa & WLAN_CAPABILITY_IMM_BACK) printf(" ImmediateBACK"); @@ -228,7 +235,7 @@ } static int print_bss_handler(struct nl_msg *msg, void *arg) -@@ -2609,8 +2622,10 @@ static int print_bss_handler(struct nl_m +@@ -2662,8 +2675,10 @@ static int print_bss_handler(struct nl_m else printf("\tfreq: %d\n", freq); @@ -239,7 +246,7 @@ } if (bss[NL80211_BSS_BEACON_INTERVAL]) printf("\tbeacon interval: %d TUs\n", -@@ -2804,6 +2819,7 @@ static int handle_stop_sched_scan(struct +@@ -2857,6 +2872,7 @@ static int handle_stop_sched_scan(struct return 0; } @@ -247,7 +254,7 @@ COMMAND(scan, sched_start, SCHED_SCAN_OPTIONS, NL80211_CMD_START_SCHED_SCAN, 0, CIB_NETDEV, handle_start_sched_scan, -@@ -2814,3 +2830,4 @@ COMMAND(scan, sched_start, +@@ -2867,3 +2883,4 @@ COMMAND(scan, sched_start, COMMAND(scan, sched_stop, "", NL80211_CMD_STOP_SCHED_SCAN, 0, CIB_NETDEV, handle_stop_sched_scan, "Stop an ongoing scheduled scan."); From 4044ce7109660d18bfc39cb392052581f44be80d Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Fri, 2 May 2025 21:01:48 +0800 Subject: [PATCH 11/17] kernel: add missing Kconfig symbols Found when building rockchip target (with kernel 6.12). Signed-off-by: Tianling Shen Link: https://github.com/openwrt/openwrt/pull/18685 Signed-off-by: Robert Marko --- target/linux/generic/config-6.12 | 1 + target/linux/rockchip/armv8/config-6.6 | 1 + 2 files changed, 2 insertions(+) diff --git a/target/linux/generic/config-6.12 b/target/linux/generic/config-6.12 index 1f30dffb30..b7f3b8b019 100644 --- a/target/linux/generic/config-6.12 +++ b/target/linux/generic/config-6.12 @@ -1627,6 +1627,7 @@ CONFIG_DQL=y # CONFIG_DRM_PARADE_PS8622 is not set # CONFIG_DRM_PARADE_PS8640 is not set # CONFIG_DRM_PL111 is not set +# CONFIG_DRM_POWERVR is not set # CONFIG_DRM_QXL is not set # CONFIG_DRM_RADEON is not set # CONFIG_DRM_RADEON_USERPTR is not set diff --git a/target/linux/rockchip/armv8/config-6.6 b/target/linux/rockchip/armv8/config-6.6 index c50372016e..4ad3a292c6 100644 --- a/target/linux/rockchip/armv8/config-6.6 +++ b/target/linux/rockchip/armv8/config-6.6 @@ -550,6 +550,7 @@ CONFIG_RATIONAL=y # CONFIG_RAVE_SP_CORE is not set CONFIG_RCU_TRACE=y CONFIG_REALTEK_PHY=y +CONFIG_REALTEK_PHY_HWMON=y CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y CONFIG_REGMAP_IRQ=y From 2a9316fbfb6e123e0d2672a9726dc752c7f6dbdd Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 11 May 2025 15:25:54 +0200 Subject: [PATCH 12/17] ucode: update to Git HEAD (2025-05-11) 567207a9bf16 fs: implement fileno() on directory handles eb1d93235509 fs: support passing directory handle or fd in chdir() 38a2254337f1 build: detect whether toolchain employs default source fortification 6eddfc9dff17 resolv: fix fd leak in send_queries 3d36856b2dc5 uci: fix memory leak on cursor() error aafde95f1ecf uci: add cursor() flags argument d8cebc5a6bfd Revert "WIP: lib: support map() over objects" 2599cf80736b zlib: incorporate latest PR changes 830f316a7e49 socker: let sock.peercred() clear error on success 4cbac141406e types: rename u64_to_constant flag to ext_flag d802fe5da5cd types: add support for resources with embedded data/values 71b4fdc6f60b types: add support for setting resource persistent flag 141f799eba08 uloop: use container_of instead of direct pointer casts 1396f8f2988d uloop: use uc_fn_thisval 9a121fc7440c uloop: drop object_registry 11b804d97086 socket: do not clear last_error in socket.error() d5b3a9dc1091 socket: add strerror() method Fixes: https://github.com/jow-/ucode/issues/285 Signed-off-by: Felix Fietkau --- package/utils/ucode/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/utils/ucode/Makefile b/package/utils/ucode/Makefile index a342c7471f..ed155af02f 100644 --- a/package/utils/ucode/Makefile +++ b/package/utils/ucode/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://github.com/jow-/ucode.git -PKG_SOURCE_DATE:=2025-03-24 -PKG_SOURCE_VERSION:=b27d70c977ab4381f4094a0b1208e2a13fc5123f -PKG_MIRROR_HASH:=30a19d71a55ac320c92879beaed18a2f8da7b3b523eb7effa34ad3c4f9e1e50d +PKG_SOURCE_DATE:=2025-05-11 +PKG_SOURCE_VERSION:=d5b3a9dc1091dd28cf6f0f60cd34fc322ef27717 +PKG_MIRROR_HASH:=cd8af9d5ac28e2530b56015a3f2fcf6f36062546cac8b23a5f7b75b367209b54 PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=ISC From 44ef34350095c86227ea0cf84b816258c5195e29 Mon Sep 17 00:00:00 2001 From: Konstantin Demin Date: Mon, 12 May 2025 09:25:58 +0300 Subject: [PATCH 13/17] toolchain: gcc: fix build error with glibc for aarch64 targets GCC 14+ fails to build due to libatomic specific -march handling. This build error triggers only with glibc and not with musl libc which is default. Related: https://github.com/openwrt/openwrt/issues/16073 Signed-off-by: Konstantin Demin Link: https://github.com/openwrt/openwrt/pull/18647 Signed-off-by: Robert Marko --- .../patches-14.x/830-aarch64-libatomic.patch | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 toolchain/gcc/patches-14.x/830-aarch64-libatomic.patch diff --git a/toolchain/gcc/patches-14.x/830-aarch64-libatomic.patch b/toolchain/gcc/patches-14.x/830-aarch64-libatomic.patch new file mode 100644 index 0000000000..e43596a253 --- /dev/null +++ b/toolchain/gcc/patches-14.x/830-aarch64-libatomic.patch @@ -0,0 +1,32 @@ +libatomic: Do not enforce march on aarch64 + +Inspired by The Yocto Project [1]. + +[1] https://github.com/yoctoproject/poky/blob/51192a79f1717786dda42776f916c3d97ada7971/meta/recipes-devtools/gcc/gcc/0022-libatomic-Do-not-enforce-march-on-aarch64.patch + +Signed-off-by: Konstantin Demin + + libatomic/Makefile.am | 1 - + libatomic/Makefile.in | 1 - + 2 files changed, 2 deletions(-) + +--- a/libatomic/Makefile.am ++++ b/libatomic/Makefile.am +@@ -130,7 +130,6 @@ libatomic_la_LIBADD = $(foreach s,$(SIZES),$(addsuffix _$(s)_.lo,$(SIZEOBJS))) + ## On a target-specific basis, include alternates to be selected by IFUNC. + if HAVE_IFUNC + if ARCH_AARCH64_LINUX +-IFUNC_OPTIONS = -march=armv8-a+lse + libatomic_la_LIBADD += $(foreach s,$(SIZES),$(addsuffix _$(s)_1_.lo,$(SIZEOBJS))) + + endif +--- a/libatomic/Makefile.in ++++ b/libatomic/Makefile.in +@@ -452,7 +452,6 @@ M_SRC = $(firstword $(filter %/$(M_FILE), $(all_c_files))) + libatomic_la_LIBADD = $(foreach s,$(SIZES),$(addsuffix \ + _$(s)_.lo,$(SIZEOBJS))) $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) +-@ARCH_AARCH64_LINUX_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=armv8-a+lse + @ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=armv7-a+fp -DHAVE_KERNEL64 + @ARCH_I386_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=i586 + @ARCH_X86_64_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -mcx16 -mcx16 From 929702fdc514c0ec77e93a407be741aa5e375b1e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 12 May 2025 11:00:34 +0200 Subject: [PATCH 14/17] unetmsg: reconnect on loss of tx connection Avoids half-connected broken state Signed-off-by: Felix Fietkau --- .../unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc b/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc index cfb702ad94..cf92a67e13 100644 --- a/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc +++ b/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc @@ -337,6 +337,10 @@ function network_open_channel(net, name, peer) delete net.tx_channels[sock_data.name]; network_tx_socket_close(sock_data); + if (net.timer.remaining() > 0) + return; + + net.timer.set(sock_data.auth ? 100 : 10000); }; sock_data.socket = sock; From 9bdbe24176ca32925e4aaa3f8650d5eb11fdfc5f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 12 May 2025 11:13:44 +0200 Subject: [PATCH 15/17] unetmsg: ping on tx channel after new incoming connection Ensure that stale connections are timed out faster Signed-off-by: Felix Fietkau --- .../files/usr/share/ucode/unetmsg/unetmsgd-remote.uc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc b/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc index cf92a67e13..d905dbd349 100644 --- a/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc +++ b/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc @@ -191,8 +191,18 @@ function network_check_auth(sock_data, info) sock_data.auth = true; net.rx_channels[sock_data.name] = sock_data; core.dbg(`Incoming connection from ${sock_data.name} established\n`); - if (!net.tx_channels[sock_data.name]) + + let chan = net.tx_channels[sock_data.name]; + if (!chan) { net.timer.set(100); + return; + } + + chan.channel.request({ + method: "ping", + data: {}, + return: "ignore", + }); } function network_accept(net, sock, addr) From 6e60ce007bc3a7410aa1cf75256b9879cf10e25a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 12 May 2025 11:15:09 +0200 Subject: [PATCH 16/17] unetmsg: clean up remote data when replacing the incoming connection Ensure that pub/sub state is in sync Signed-off-by: Felix Fietkau --- .../share/ucode/unetmsg/unetmsgd-remote.uc | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc b/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc index d905dbd349..65cdfac04a 100644 --- a/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc +++ b/package/network/services/unetmsg/files/usr/share/ucode/unetmsg/unetmsgd-remote.uc @@ -46,6 +46,15 @@ function network_socket_close(data) data.socket.close(); } +function network_rx_cleanup_state(name) +{ + for (let name, sub in core.remote_subscribe) + delete sub[name]; + + for (let name, sub in core.remote_publish) + delete sub[name]; +} + function network_rx_socket_close(data) { if (!data) @@ -53,14 +62,10 @@ function network_rx_socket_close(data) core.dbg(`Incoming connection from ${data.name} closed\n`); let net = networks[data.network]; - if (net && net.rx_channels[data.name] == data) + if (net && net.rx_channels[data.name] != data) { delete net.rx_channels[data.name]; - - for (let name, sub in core.remote_subscribe) - delete sub[data.name]; - - for (let name, sub in core.remote_publish) - delete sub[data.name]; + network_rx_cleanup_state(data.name); + } network_socket_close(data); } @@ -189,6 +194,7 @@ function network_check_auth(sock_data, info) if (sock_data.timer) sock_data.timer.cancel(); sock_data.auth = true; + network_rx_cleanup_state(sock_data.name); net.rx_channels[sock_data.name] = sock_data; core.dbg(`Incoming connection from ${sock_data.name} established\n`); From 87bfde67f2504bbd649e185fc15619d769ab9b26 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 12 May 2025 12:46:12 +0200 Subject: [PATCH 17/17] ucode: ubus: fix use-after-free on deferred request reply() method Hold a reference to the defer resource as long as it is still needed Signed-off-by: Felix Fietkau --- ...er-free-on-deferred-request-reply-me.patch | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 package/utils/ucode/patches/020-ubus-fix-use-after-free-on-deferred-request-reply-me.patch diff --git a/package/utils/ucode/patches/020-ubus-fix-use-after-free-on-deferred-request-reply-me.patch b/package/utils/ucode/patches/020-ubus-fix-use-after-free-on-deferred-request-reply-me.patch new file mode 100644 index 0000000000..142595a5bd --- /dev/null +++ b/package/utils/ucode/patches/020-ubus-fix-use-after-free-on-deferred-request-reply-me.patch @@ -0,0 +1,27 @@ +From: Felix Fietkau +Date: Mon, 12 May 2025 12:43:44 +0200 +Subject: [PATCH] ubus: fix use-after-free on deferred request reply() method + +Hold a reference to the defer resource as long as it is still needed + +Signed-off-by: Felix Fietkau +--- + +--- a/lib/ubus.c ++++ b/lib/ubus.c +@@ -636,6 +636,7 @@ uc_ubus_call_user_cb(uc_ubus_deferred_t + uc_value_t *this, *func; + + request_reg_get(defer->vm, defer->registry_index, &this, &func, NULL, NULL); ++ ucv_get(this); + + if (ucv_is_callable(func)) { + uc_vm_stack_push(defer->vm, ucv_get(this)); +@@ -648,6 +649,7 @@ uc_ubus_call_user_cb(uc_ubus_deferred_t + } + + request_reg_clear(defer->vm, defer->registry_index); ++ ucv_put(this); + } + + static void