Merge Official Source
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
commit
c2b634f5e9
|
@ -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 <dedeckeh@gmail.com>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
From 966c590bc4dcbd9a69fdf8fe9f41cec00e72e376 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Eskew <dylan.eskew@candelatech.com>
|
||||
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 <dylan.eskew@candelatech.com>
|
||||
Link: https://patch.msgid.link/20240930181145.1043048-2-dylan.eskew@candelatech.com
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
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,
|
|
@ -0,0 +1,482 @@
|
|||
From a0a7ddef29fc412cee7e3ca027905218b145a40f Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Eskew <dylan.eskew@candelatech.com>
|
||||
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 <dylan.eskew@candelatech.com>
|
||||
Link: https://patch.msgid.link/20241122161851.647214-1-dylan.eskew@candelatech.com
|
||||
[cleanups]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
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(" <no flags>");
|
||||
@@ -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 */) {
|
|
@ -0,0 +1,207 @@
|
|||
From 4c859917316b69e66ba241d85b4da6ee01292a11 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Eskew <dylan.eskew@candelatech.com>
|
||||
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 <dylan.eskew@candelatech.com>
|
||||
Link: https://patch.msgid.link/20250319183918.1215853-2-dylan.eskew@candelatech.com
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
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)
|
|
@ -0,0 +1,175 @@
|
|||
From a6ad3f11ead18d1812c7d3759991dc22b20d90da Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Eskew <dylan.eskew@candelatech.com>
|
||||
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 <dylan.eskew@candelatech.com>
|
||||
Link: https://patch.msgid.link/20250319183918.1215853-3-dylan.eskew@candelatech.com
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
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;
|
|
@ -0,0 +1,107 @@
|
|||
From 59660a349cf35903e951f99bdd8a74df063c912e Mon Sep 17 00:00:00 2001
|
||||
From: Aleksander Jan Bajkowski <olek2@wp.pl>
|
||||
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 <olek2@wp.pl>
|
||||
Link: https://patch.msgid.link/20250502194405.3489240-1-olek2@wp.pl
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
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])
|
|
@ -0,0 +1,131 @@
|
|||
From 8ea80d378ce5f727e69493533a666278c6a568a7 Mon Sep 17 00:00:00 2001
|
||||
From: Aleksander Jan Bajkowski <olek2@wp.pl>
|
||||
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 <olek2@wp.pl>
|
||||
Link: https://patch.msgid.link/20250502100353.3149470-1-olek2@wp.pl
|
||||
[add default case to bandwidth switch]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
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;
|
|
@ -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.");
|
||||
|
|
|
@ -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 <jo@mein.io>
|
||||
PKG_LICENSE:=ISC
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
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 <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- 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
|
|
@ -79,14 +79,14 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led-1 {
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
|
||||
};
|
||||
|
||||
led-2 {
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
|
@ -101,14 +101,14 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led-1 {
|
||||
led@1 {
|
||||
reg = <1>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
|
||||
};
|
||||
|
||||
led-2 {
|
||||
led@2 {
|
||||
reg = <2>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "mt7621.dtsi"
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
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 = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
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 = <LED_COLOR_ID_GREEN>;
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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 = <KEY_A>;
|
||||
};
|
||||
|
||||
/* Touch area 5 GHz */
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
|
||||
semtech,cin-delta = <0x3>;
|
||||
semtech,sense-threshold = <0x04>;
|
||||
|
||||
linux,keycodes = <KEY_B>;
|
||||
};
|
||||
/* Touch area WPS */
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
|
||||
semtech,cin-delta = <0x3>;
|
||||
semtech,sense-threshold = <0x04>;
|
||||
|
||||
linux,keycodes = <KEY_WPS_BUTTON>;
|
||||
};
|
||||
|
||||
channel@4 {
|
||||
reg = <4>;
|
||||
|
||||
led {
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
function = LED_FUNCTION_WAN;
|
||||
};
|
||||
};
|
||||
|
||||
channel@5 {
|
||||
reg = <5>;
|
||||
|
||||
led {
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_WAN;
|
||||
};
|
||||
};
|
||||
|
||||
channel@6 {
|
||||
reg = <6>;
|
||||
|
||||
led {
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_WLAN_5GHZ;
|
||||
linux,default-trigger = "phy1tpt";
|
||||
};
|
||||
};
|
||||
|
||||
channel@7 {
|
||||
reg = <7>;
|
||||
|
||||
led {
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_WLAN_2GHZ;
|
||||
linux,default-trigger = "phy0tpt";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -0,0 +1,560 @@
|
|||
From ba92c0187006e2a6eae9573a569d275b0bd31732 Mon Sep 17 00:00:00 2001
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
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 <mail@david-bauer.net>
|
||||
---
|
||||
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 <mail@david-bauer.net>
|
||||
+ */
|
||||
+
|
||||
+ #include <linux/kernel.h>
|
||||
+ #include <linux/module.h>
|
||||
+ #include <linux/input.h>
|
||||
+ #include <linux/leds.h>
|
||||
+ #include <linux/of.h>
|
||||
+ #include <linux/regmap.h>
|
||||
+ #include <linux/i2c.h>
|
||||
+ #include <linux/gpio/consumer.h>
|
||||
+ #include <linux/bitfield.h>
|
||||
+
|
||||
+ /* 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 <mail@david-bauer.net>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
2.47.2
|
||||
|
|
@ -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 <rockdrilla@gmail.com>
|
||||
|
||||
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
|
Loading…
Reference in New Issue