From b4b6346cdc5a6667f0e7d009e5776920bac6d480 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 9 Dec 2022 14:54:54 +0000 Subject: [PATCH] mgmt: mcumgr: Make Bluetooth and UDP transport init automatic This moves the UDP and Bluetooth initialisation for MCUmgr to be performed automatically with the new hander registration feature. Signed-off-by: Jamie McCrae --- include/zephyr/mgmt/mcumgr/transport/smp_bt.h | 29 +++++---- .../mgmt/mcumgr/smp_svr/src/bluetooth.c | 25 +------- .../subsys/mgmt/mcumgr/smp_svr/src/common.h | 3 +- samples/subsys/mgmt/mcumgr/smp_svr/src/main.c | 5 +- .../mgmt/mcumgr/transport/Kconfig.bluetooth | 20 +++++++ subsys/mgmt/mcumgr/transport/Kconfig.udp | 9 +++ subsys/mgmt/mcumgr/transport/src/smp_bt.c | 59 +++++++++++++++++-- subsys/mgmt/mcumgr/transport/src/smp_udp.c | 44 +++++++++++++- 8 files changed, 149 insertions(+), 45 deletions(-) diff --git a/include/zephyr/mgmt/mcumgr/transport/smp_bt.h b/include/zephyr/mgmt/mcumgr/transport/smp_bt.h index dff48d8dc4c..adceff179b6 100644 --- a/include/zephyr/mgmt/mcumgr/transport/smp_bt.h +++ b/include/zephyr/mgmt/mcumgr/transport/smp_bt.h @@ -19,28 +19,37 @@ extern "C" { #endif /** - * @brief Registers the SMP Bluetooth service. + * @brief Registers the SMP Bluetooth service. Should only be called if the Bluetooth + * transport has been unregistered by calling smp_bt_unregister(). * - * @return 0 on success; negative error code on failure. + * @return 0 on success; negative error code on failure. */ int smp_bt_register(void); /** - * @brief Unregisters the SMP Bluetooth service. + * @brief Unregisters the SMP Bluetooth service. * - * @return 0 on success; negative error code on failure. + * @return 0 on success; negative error code on failure. */ int smp_bt_unregister(void); /** - * Transmits an SMP command/response over the specified Bluetooth connection - * as a notification. + * @brief Sets up the Bluetooth SMP (MCUmgr) transport. This should be called if the Kconfig + * option ``CONFIG_MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT`` is not enabled, this will + * register the transport and add it to the Bluetooth registered services so that + * clients can access registered MCUmgr commands. + */ +void smp_bt_start(void); + +/** + * @brief Transmits an SMP command/response over the specified Bluetooth connection as a + * notification. * - * @param conn Connection object. - * @param data Pointer to SMP message. - * @param len data length. + * @param conn Connection object. + * @param data Pointer to SMP message. + * @param len data length. * - * @return 0 in case of success or negative value in case of error. + * @return 0 in case of success or negative value in case of error. */ int smp_bt_notify(struct bt_conn *conn, const void *data, uint16_t len); diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c b/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c index 4e38793902c..1c6ce8dbd58 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c +++ b/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c @@ -58,30 +58,9 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { .disconnected = disconnected, }; -static void bt_ready(int err) -{ - if (err) { - LOG_ERR("Bluetooth init failed (err %d)", err); - return; - } - - LOG_INF("Bluetooth initialized"); - - k_work_submit(&advertise_work); -} - -void start_smp_bluetooth(void) +void start_smp_bluetooth_adverts(void) { k_work_init(&advertise_work, advertise); - /* Enable Bluetooth. */ - int rc = bt_enable(bt_ready); - - if (rc != 0) { - LOG_ERR("Bluetooth init failed (err %d)", rc); - return; - } - - /* Initialize the Bluetooth mcumgr transport. */ - smp_bt_register(); + k_work_submit(&advertise_work); } diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/src/common.h b/samples/subsys/mgmt/mcumgr/smp_svr/src/common.h index 4a765137e4b..3e7398df0b8 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/src/common.h +++ b/samples/subsys/mgmt/mcumgr/smp_svr/src/common.h @@ -4,5 +4,4 @@ * SPDX-License-Identifier: Apache-2.0 */ -void start_smp_bluetooth(void); -void start_smp_udp(void); +void start_smp_bluetooth_adverts(void); diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c b/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c index 23ea1fb7f49..aee7c249a10 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c +++ b/samples/subsys/mgmt/mcumgr/smp_svr/src/main.c @@ -67,10 +67,7 @@ void main(void) } #endif #ifdef CONFIG_MCUMGR_SMP_BT - start_smp_bluetooth(); -#endif -#ifdef CONFIG_MCUMGR_SMP_UDP - start_smp_udp(); + start_smp_bluetooth_adverts(); #endif if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) { diff --git a/subsys/mgmt/mcumgr/transport/Kconfig.bluetooth b/subsys/mgmt/mcumgr/transport/Kconfig.bluetooth index a0ce398fbba..079230160ca 100644 --- a/subsys/mgmt/mcumgr/transport/Kconfig.bluetooth +++ b/subsys/mgmt/mcumgr/transport/Kconfig.bluetooth @@ -87,4 +87,24 @@ config MCUMGR_SMP_BT_CONN_PARAM_CONTROL_RETRY_TIME endif # MCUMGR_SMP_BT_CONN_PARAM_CONTROL +config MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT + bool "Bluetooth SMP stack enable autostart/setup" + default y + help + If this option is enabled, then the Bluetooth stack will be enabled + when the Bluetooth SMP (MCUmgr) transport initialises. If another + system or the application does this, then this option should be + disabled. Note that Bluetooth will need to be enabled prior to the + Bluetooth SMP (MCUmgr) transport being initialised (by calling + ``smp_bt_start()``) if this option is disabled. + +config MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT_WAIT + bool "Bluetooth SMP wait for autostart/setup completion" + default y + depends on MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT + help + If this option is enabled, then the setup handler will wait for the + Bluetooth stack to become ready from the ``bt_enable()`` call, + otherwise will return instantly without waiting. + endif # MCUMGR_SMP_BT diff --git a/subsys/mgmt/mcumgr/transport/Kconfig.udp b/subsys/mgmt/mcumgr/transport/Kconfig.udp index 634258f8155..9aa0e4dc104 100644 --- a/subsys/mgmt/mcumgr/transport/Kconfig.udp +++ b/subsys/mgmt/mcumgr/transport/Kconfig.udp @@ -56,4 +56,13 @@ config MCUMGR_SMP_UDP_MTU MCUMGR_SMP_UDP_MTU <= MCUMGR_BUF_SIZE + SMP msg overhead - address size where address size is determined by IPv4/IPv6 selection. +config MCUMGR_TRANSPORT_UDP_AUTOMATIC_INIT + bool "UDP SMP autostart/setup" + default y + help + Enable setting up the UDP SMP transport at boot time without needing + any code in the application to do this. Will automatically start the + UDP SMP service when the network interface is up and disable it when + it goes down (at layer 4). + endif # MCUMGR_SMP_UDP diff --git a/subsys/mgmt/mcumgr/transport/src/smp_bt.c b/subsys/mgmt/mcumgr/transport/src/smp_bt.c index 52e46afbc8d..4c066e82eec 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_bt.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_bt.c @@ -9,7 +9,6 @@ * @brief Bluetooth transport for the mcumgr SMP protocol. */ - #include #include #include @@ -24,6 +23,10 @@ #include #include +#ifdef CONFIG_MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT +#include +#endif + #include LOG_MODULE_DECLARE(mcumgr_smp, CONFIG_MCUMGR_SMP_LOG_LEVEL); @@ -87,6 +90,10 @@ static uint8_t next_id; static struct smp_transport smp_bt_transport; static struct conn_param_data conn_data[CONFIG_BT_MAX_CONN]; +#ifdef CONFIG_MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT +static K_SEM_DEFINE(bt_ready_sem, 0, 1); +#endif + /* SMP service. * {8D53DC1D-1DB7-4CD3-868B-8A527460AA84} */ @@ -627,10 +634,24 @@ static bool smp_bt_query_valid_check(struct net_buf *nb, void *arg) return true; } -static int smp_bt_init(const struct device *dev) +#ifdef CONFIG_MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT_WAIT +static void bt_ready(int err) { + if (err) { + LOG_ERR("Bluetooth init failed (err %d)", err); + return; + } + + LOG_INF("Bluetooth initialised"); + + k_sem_give(&bt_ready_sem); +} +#endif + +void smp_bt_start(void) +{ + int rc; uint8_t i = 0; - ARG_UNUSED(dev); next_id = 1; @@ -639,6 +660,7 @@ static int smp_bt_init(const struct device *dev) .connected = connected, .disconnected = disconnected, }; + bt_conn_cb_register(&conn_callbacks); if (IS_ENABLED(CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL)) { @@ -653,7 +675,34 @@ static int smp_bt_init(const struct device *dev) smp_transport_init(&smp_bt_transport, smp_bt_tx_pkt, smp_bt_get_mtu, smp_bt_ud_copy, smp_bt_ud_free, smp_bt_query_valid_check); - return 0; + + rc = smp_bt_register(); + + if (rc != 0) { + LOG_ERR("Bluetooth SMP transport register failed (err %d)", rc); + } } -SYS_INIT(smp_bt_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); +#ifdef CONFIG_MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT +static void smp_bt_setup(void) +{ + /* Enable Bluetooth */ +#ifdef CONFIG_MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT_WAIT + int rc = bt_enable(bt_ready); +#else + int rc = bt_enable(NULL); +#endif + + if (rc != 0) { + LOG_ERR("Bluetooth init failed (err %d)", rc); + } else { +#ifdef CONFIG_MCUMGR_TRANSPORT_BT_AUTOMATIC_INIT_WAIT + k_sem_take(&bt_ready_sem, K_FOREVER); +#endif + } + + smp_bt_start(); +} + +MCUMGR_HANDLER_DEFINE(smp_bt, smp_bt_setup); +#endif diff --git a/subsys/mgmt/mcumgr/transport/src/smp_udp.c b/subsys/mgmt/mcumgr/transport/src/smp_udp.c index 41e8d353b4d..07e74b4f8c0 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_udp.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_udp.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2019, Prevas A/S + * Copyright (c) 2019-2020, Prevas A/S + * Copyright (c) 2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +26,13 @@ #include +#ifdef CONFIG_MCUMGR_TRANSPORT_UDP_AUTOMATIC_INIT +#include +#include +#include +#include +#endif + #define LOG_LEVEL CONFIG_MCUMGR_LOG_LEVEL #include LOG_MODULE_REGISTER(smp_udp); @@ -64,6 +72,10 @@ static struct configs configs = { #endif }; +#ifdef CONFIG_MCUMGR_TRANSPORT_UDP_AUTOMATIC_INIT +static struct net_mgmt_event_callback smp_udp_mgmt_cb; +#endif + #ifdef CONFIG_MCUMGR_SMP_UDP_IPV4 static int smp_udp4_tx(struct net_buf *nb) { @@ -280,3 +292,33 @@ int smp_udp_close(void) return MGMT_ERR_EOK; } + +#ifdef CONFIG_MCUMGR_TRANSPORT_UDP_AUTOMATIC_INIT +static void smp_udp_net_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, + struct net_if *iface) +{ + ARG_UNUSED(cb); + ARG_UNUSED(iface); + + if (mgmt_event == NET_EVENT_L4_CONNECTED) { + LOG_INF("Network connected"); + + if (smp_udp_open() < 0) { + LOG_ERR("Could not open SMP UDP"); + } + } else if (mgmt_event == NET_EVENT_L4_DISCONNECTED) { + LOG_INF("Network disconnected"); + smp_udp_close(); + } +} + +static void smp_udp_start(void) +{ + net_mgmt_init_event_callback(&smp_udp_mgmt_cb, smp_udp_net_event_handler, + (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)); + net_mgmt_add_event_callback(&smp_udp_mgmt_cb); + net_conn_mgr_resend_status(); +} + +MCUMGR_HANDLER_DEFINE(smp_udp, smp_udp_start); +#endif