diff --git a/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst b/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst index a57c855e7bad4..896eb68eebc3e 100644 --- a/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst +++ b/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst @@ -173,6 +173,13 @@ network tools:: Use ``ifup wlan0``, not ``ifconfig wlan0 up``: ``ifconfig`` interprets its second argument as an IP address. +.. note:: + The station is WPA2-only. A WPA3-transition network (WPA2/WPA3 mixed + mode) associates through WPA2-PSK; a WPA3(SAE)-only network is refused + up front with ``ENOTSUP`` and a console message naming the unsupported + AKM, instead of letting the prebuilt supplicant attempt the SAE + handshake (which faults). + The RTC and the SNTP client are enabled, so the clock can be set from the network:: @@ -296,9 +303,10 @@ ble ``wapi`` plus BLE (``CONFIG_GD32VW55X_BLE``) and the demo GATT service (``CONFIG_GD32VW55X_BLE_GATT_DEMO``). The board advertises a connectable set named ``NuttX`` and registers a minimal "transparent UART" service (16-bit -UUIDs ``0xffe0`` / RX ``0xffe1`` / TX ``0xffe2``). A central connects, -discovers the service, and a write to the RX characteristic is logged on the -board console:: +UUIDs ``0xffe0`` / RX ``0xffe1`` / TX ``0xffe2``). Advertising restarts on +every disconnection, so the device stays discoverable across connections. A +central connects, discovers the service, and a write to the RX characteristic +is logged on the board console:: nsh> BLE RX (11): Hello world diff --git a/arch/risc-v/src/gd32vw55x/gdble/gd32_ble.c b/arch/risc-v/src/gd32vw55x/gdble/gd32_ble.c index 33a7277b7f6c5..76d7f1d2c2e4b 100644 --- a/arch/risc-v/src/gd32vw55x/gdble/gd32_ble.c +++ b/arch/risc-v/src/gd32vw55x/gdble/gd32_ble.c @@ -60,6 +60,7 @@ #include "ble_gap.h" #include "ble_adapter.h" #include "ble_adv.h" +#include "ble_conn.h" #include "wrapper_os.h" #include "gd32vw55x_platform.h" @@ -217,6 +218,8 @@ static void gd32_ble_adv_start(uint8_t adv_idx) * ****************************************************************************/ +static uint8_t g_adv_idx = 0xff; /* 0xff = no advertising set yet */ + static void gd32_ble_adv_evt_handler(ble_adv_evt_t adv_evt, void *p_data, void *p_context) { @@ -231,6 +234,7 @@ static void gd32_ble_adv_evt_handler(ble_adv_evt_t adv_evt, void *p_data, if (chg->state == BLE_ADV_STATE_CREATE) { + g_adv_idx = chg->adv_idx; gd32_ble_adv_start(chg->adv_idx); } else if (chg->state == BLE_ADV_STATE_START) @@ -239,6 +243,30 @@ static void gd32_ble_adv_evt_handler(ble_adv_evt_t adv_evt, void *p_data, } } +/**************************************************************************** + * Name: gd32_ble_conn_evt_handler + * + * Description: + * A connection stops the legacy advertising set and the stack leaves it + * stopped, so after the first central connects (or aborts the attempt) + * the device would never be discoverable again until a reset. Restart + * the set on every disconnection. + * + ****************************************************************************/ + +static void gd32_ble_conn_evt_handler(ble_conn_evt_t event, + ble_conn_data_u *p_data) +{ + if (event == BLE_CONN_EVT_STATE_CHG && + p_data->conn_state.state == BLE_CONN_STATE_DISCONNECTD && + g_adv_idx != 0xff) + { + wlinfo("BLE disconnected (reason 0x%x), restarting advertising\n", + p_data->conn_state.info.discon_info.reason); + ble_adv_restart(g_adv_idx); + } +} + /**************************************************************************** * Name: gd32_ble_adv_create * @@ -483,6 +511,10 @@ int gd32_ble_initialize(void) ble_adp_callback_register(gd32_ble_adp_evt_handler); + /* Restart advertising when a central disconnects */ + + ble_conn_callback_register(gd32_ble_conn_evt_handler); + #ifdef CONFIG_GD32VW55X_BLE_GATT_DEMO /* Register the demo GATT service (RX write / TX notify) */ diff --git a/arch/risc-v/src/gd32vw55x/gdwifi/Wireless.mk b/arch/risc-v/src/gd32vw55x/gdwifi/Wireless.mk index 2f50eb366f183..1ccdbfa68cf2f 100644 --- a/arch/risc-v/src/gd32vw55x/gdwifi/Wireless.mk +++ b/arch/risc-v/src/gd32vw55x/gdwifi/Wireless.mk @@ -33,6 +33,14 @@ # not use: WPA comes from the lightweight libwpas.a, via wifi_wpa.c. CFLAGS += -DCFG_RTOS -DEXEC_USING_STD_PRINTF -DGDWIFI_NUTTX +# The vendor SDK sources are not NuttX-warning-clean (undefined macros in +# #if, %d for uint32_t, shadowed locals, K&R prototypes, ...). These +# suppressions are scoped to this chip's build; the macro redefinitions +# that no -Wno flag covers are fixed in the SDK patch instead +# (riscv_encoding.h, wifi_management.h). +CFLAGS += -Wno-undef -Wno-format -Wno-shadow -Wno-address +CFLAGS += -Wno-unused-function -Wno-strict-prototypes -Wno-array-parameter + # Include paths: our patched config dir must come first INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)gd32vw55x$(DELIM)gdwifi$(DELIM)config diff --git a/arch/risc-v/src/gd32vw55x/gdwifi/config/build_config.h b/arch/risc-v/src/gd32vw55x/gdwifi/config/build_config.h index c923b0f43f370..e8a4c7050cee7 100644 --- a/arch/risc-v/src/gd32vw55x/gdwifi/config/build_config.h +++ b/arch/risc-v/src/gd32vw55x/gdwifi/config/build_config.h @@ -8,6 +8,19 @@ #include_next "build_config.h" +/* The port is WPA2-only: the SAE (WPA3) handshake faults inside the + * prebuilt supplicant (load access fault in the elliptic-curve math). + * Undefining CONFIG_WPA3_SAE activates the vendor's own fallback in + * wifi_netlink.c: the SAE/OWE AKMs are stripped from the connection + * config and the SAE auth algorithm is never selected, so a + * WPA3-transition AP associates through WPA2-PSK and an SAE-only AP is + * rejected by the AP instead of crashing the supplicant. (The glue also + * refuses SAE-only networks up front with a clear error -- see + * gdwifi_netdev.c.) + */ + +#undef CONFIG_WPA3_SAE + #ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN 1234 #endif diff --git a/arch/risc-v/src/gd32vw55x/gdwifi/gdwifi_netdev.c b/arch/risc-v/src/gd32vw55x/gdwifi/gdwifi_netdev.c index 6c02639226aa3..df7fb4299d5c9 100644 --- a/arch/risc-v/src/gd32vw55x/gdwifi/gdwifi_netdev.c +++ b/arch/risc-v/src/gd32vw55x/gdwifi/gdwifi_netdev.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -528,7 +529,6 @@ static int gdwifi_ifdown(struct netdev_lowerhalf_s *dev) static int gdwifi_transmit(struct netdev_lowerhalf_s *dev, netpkt_t *pkt) { - struct gdwifi_dev_s *priv = (struct gdwifi_dev_s *)dev; unsigned int len = netpkt_getdatalen(dev, pkt); struct pbuf *p; @@ -599,6 +599,74 @@ static int g_mode = IW_MODE_INFRA; /* INFRA = station, MASTER = softAP */ #define GDWIFI_AUTH_WPA2 3 /* AUTH_MODE_WPA2 (SAE/WPA3 no AP estoura o crypto) */ #define GDWIFI_AP_CHANNEL 11 +/**************************************************************************** + * Name: gdwifi_target_supported + * + * Description: + * The port is WPA2-only (the SAE handshake faults inside the prebuilt + * supplicant), so refuse a network that offers no AKM we can complete -- + * WPA3(SAE)-only being the common case -- with a clear error instead of + * letting the association fail obscurely. A targeted blocking scan + * fetches the AKM bitmap of the AP; if the network cannot be found the + * decision is left to the vendor connect path (same behavior as today). + * + ****************************************************************************/ + +static int gdwifi_target_supported(void) +{ + struct macif_scan_results *results; + size_t ssid_len = strlen(g_essid); + uint32_t supported = CO_BIT(MAC_AKM_NONE) | CO_BIT(MAC_AKM_PRE_RSN) | + CO_BIT(MAC_AKM_PSK) | CO_BIT(MAC_AKM_PSK_SHA256); + int ret = OK; + uint32_t i; + + if (wifi_management_scan(1, g_essid) != 0) + { + return OK; + } + + results = sys_malloc(sizeof(*results)); + if (results == NULL) + { + return -ENOMEM; + } + + if (wifi_netlink_scan_results_get(GDWIFI_VIF_STA, results) != 0) + { + sys_mfree(results); + return OK; + } + + for (i = 0; i < results->result_cnt; i++) + { + struct mac_scan_result *ap = &results->result[i]; + + if (!ap->valid_flag || ap->ssid.length != ssid_len || + memcmp(ap->ssid.array, g_essid, ssid_len) != 0) + { + continue; + } + + if ((ap->akm & supported) == 0) + { + /* syslog, not nerr: the rejection must be visible in release + * configs too, or the refused connect looks like a silent no-op. + */ + + syslog(LOG_ERR, "gdwifi: '%s' offers no supported AKM (bitmap " + "0x%lx): WPA3/SAE, OWE and 802.1X are not supported, " + "WPA2-PSK only\n", g_essid, (unsigned long)ap->akm); + ret = -ENOTSUP; + } + + break; + } + + sys_mfree(results); + return ret; +} + static int gdwifi_connect(struct netdev_lowerhalf_s *dev) { int ret; @@ -623,6 +691,12 @@ static int gdwifi_connect(struct netdev_lowerhalf_s *dev) return ret == 0 ? OK : -EAGAIN; } + ret = gdwifi_target_supported(); + if (ret < 0) + { + return ret; + } + ninfo("connect '%s'\n", g_essid); ret = wifi_management_connect(g_essid, g_passwd[0] ? g_passwd : NULL, 1); diff --git a/arch/risc-v/src/gd32vw55x/gdwifi/patches/0001-nuttx-port.patch b/arch/risc-v/src/gd32vw55x/gdwifi/patches/0001-nuttx-port.patch index 346237efd391b..526fcca2f3193 100644 --- a/arch/risc-v/src/gd32vw55x/gdwifi/patches/0001-nuttx-port.patch +++ b/arch/risc-v/src/gd32vw55x/gdwifi/patches/0001-nuttx-port.patch @@ -1,3 +1,53 @@ +diff --git a/MSDK/plf/riscv/NMSIS/Core/Include/riscv_encoding.h b/MSDK/plf/riscv/NMSIS/Core/Include/riscv_encoding.h +index 8b87225..51cb931 100644 +--- a/MSDK/plf/riscv/NMSIS/Core/Include/riscv_encoding.h ++++ b/MSDK/plf/riscv/NMSIS/Core/Include/riscv_encoding.h +@@ -31,6 +31,45 @@ + * The following macros are used for CSR encodings + * @{ + */ ++/* NuttX port: the NuttX (pulled in through ) ++ * already defines several of these names with its own encodings; undefine ++ * them so this header provides the NMSIS values to the SDK sources without ++ * macro redefinition warnings. ++ */ ++ ++#undef CSR_FCSR ++#undef CSR_FFLAGS ++#undef CSR_FRM ++#undef CSR_MINTSTATUS ++#undef CSR_USTATUS ++#undef MIE_MEIE ++#undef MIE_MSIE ++#undef MIE_MTIE ++#undef MIE_SEIE ++#undef MIE_SSIE ++#undef MIE_STIE ++#undef MIP_MEIP ++#undef MIP_MSIP ++#undef MIP_MTIP ++#undef MIP_SEIP ++#undef MIP_SSIP ++#undef MIP_STIP ++#undef MSTATUS_FS ++#undef MSTATUS_FS_CLEAN ++#undef MSTATUS_FS_DIRTY ++#undef MSTATUS_MIE ++#undef MSTATUS_MPIE ++#undef MSTATUS_MPRV ++#undef MSTATUS_MXR ++#undef MSTATUS_SIE ++#undef MSTATUS_SPIE ++#undef MSTATUS_UIE ++#undef MSTATUS_XS ++#undef SSTATUS_FS ++#undef SSTATUS_SIE ++#undef SSTATUS_SPIE ++#undef SSTATUS_XS ++ + /* === Standard CSR bit mask === */ + #define MSTATUS_UIE 0x00000001 + #define MSTATUS_SIE 0x00000002 diff --git a/MSDK/plf/riscv/gd32vw55x/gd32vw55x.h b/MSDK/plf/riscv/gd32vw55x/gd32vw55x.h index f4e200e..c9189ca 100644 --- a/MSDK/plf/riscv/gd32vw55x/gd32vw55x.h @@ -37,6 +87,24 @@ index e7f393f..8731cb8 100644 /* 2. wifi power on */ wifi_exist_flag = 1; +diff --git a/MSDK/wifi_manager/wifi_management.h b/MSDK/wifi_manager/wifi_management.h +index 3a108f9..3923f02 100644 +--- a/MSDK/wifi_manager/wifi_management.h ++++ b/MSDK/wifi_manager/wifi_management.h +@@ -94,6 +94,13 @@ extern "C" { + #define wifi_sm_printf(...) + #endif + ++/* NuttX port: also defines COMPILE_TIME_ASSERT; use the ++ * SDK's own definition here without redefining the other one. ++ */ ++#ifdef COMPILE_TIME_ASSERT ++#undef COMPILE_TIME_ASSERT ++#endif ++ + #define COMPILE_TIME_ASSERT(constant_expr) \ + do { \ + switch(0) { \ diff --git a/MSDK/wifi_manager/wifi_netlink.c b/MSDK/wifi_manager/wifi_netlink.c index aec26cc..445c109 100644 --- a/MSDK/wifi_manager/wifi_netlink.c diff --git a/arch/risc-v/src/gd32vw55x/gdwifi/wrapper_nuttx.c b/arch/risc-v/src/gd32vw55x/gdwifi/wrapper_nuttx.c index 27d651823db43..6264aae5a6e23 100644 --- a/arch/risc-v/src/gd32vw55x/gdwifi/wrapper_nuttx.c +++ b/arch/risc-v/src/gd32vw55x/gdwifi/wrapper_nuttx.c @@ -1033,28 +1033,6 @@ void sys_sched_unlock(void) * Public Functions - timers ****************************************************************************/ -static void timer_worker_fixed(void *arg) -{ - struct nx_timer_s *t = arg; - - if (!t->active) - { - return; - } - - if (t->periodic) - { - wd_start(&t->wdog, MSEC2TICK(t->delay_ms), timer_wdog_handler, - (wdparm_t)(uintptr_t)t); - } - else - { - t->active = 0; - } - - t->func(t, t->arg); -} - void sys_timer_init(os_timer_t *timer, const uint8_t *name, uint32_t delay, uint8_t periodic, timer_func_t func, void *arg) { diff --git a/arch/risc-v/src/gd32vw55x/hardware/gd32vw55x_eclic.h b/arch/risc-v/src/gd32vw55x/hardware/gd32vw55x_eclic.h index 4c8027382d0ea..8cdb2a7e01577 100644 --- a/arch/risc-v/src/gd32vw55x/hardware/gd32vw55x_eclic.h +++ b/arch/risc-v/src/gd32vw55x/hardware/gd32vw55x_eclic.h @@ -86,10 +86,14 @@ #define ECLIC_INTCTL_LEVEL(l) ((((l) & 0xf) << 4) | 0x0f) -/* Nuclei-specific CSRs used with the ECLIC */ +/* Nuclei-specific CSRs used with the ECLIC. Note: the Nuclei interrupt + * level status CSR lives at 0x346, not at the standard CLIC MINTSTATUS + * address that arch/risc-v/include/csr.h names CSR_MINTSTATUS (0xfb1); a + * distinct name avoids redefining it. + */ #define CSR_MTVT 0x307 /* Vector table base */ -#define CSR_MINTSTATUS 0x346 /* Interrupt level status */ +#define CSR_NUCLEI_MINTSTATUS 0x346 /* Interrupt level status */ #define CSR_MCACHE_CTL 0x7ca /* I-cache control */ #define CSR_MMISC_CTL 0x7d0 /* Misc control (NMI base) */ #define CSR_MTVT2 0x7ec /* Non-vectored irq entry */