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 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 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..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,10 +194,21 @@ 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`); - 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) @@ -337,6 +353,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; 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."); 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 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 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; diff --git a/target/linux/lantiq/image/tp-link_legacy.mk b/target/linux/lantiq/image/tp-link_legacy.mk index c045937838..1c6fc24899 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 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/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 2ec6498322..ad8a22ad79 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; @@ -21,3 +21,83 @@ gpios = <&gpio 12 GPIO_ACTIVE_LOW>; }; }; + +&i2c_gpio { + 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 7512177897..08e22c2b0a 100755 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -769,6 +769,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 @@ -1413,7 +1423,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/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/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index c3948a58cb..f12b150017 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,9 +59,11 @@ 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" ;; +cudy,r700|\ cudy,wr2100) ucidef_set_led_netdev "lan1" "lan1" "green:lan1" "lan1" ucidef_set_led_netdev "lan2" "lan2" "green:lan2" "lan2" 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 + 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