diff --git a/examples/platforms/openthread-select.h b/examples/platforms/openthread-select.h new file mode 100644 index 000000000..ed68839d5 --- /dev/null +++ b/examples/platforms/openthread-select.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2025, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief + * This file defines the APIs for integrating with select() based event loop. + */ + +#ifndef OPENTHREAD_SELECT_H_ +#define OPENTHREAD_SELECT_H_ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Updates the file descriptor sets with file descriptors used by OpenThread drivers. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[in,out] aMaxFd A pointer to the max file descriptor. + * @param[in,out] aReadFdSet A pointer to the read file descriptors, which may already contain some FDs. + * @param[in,out] aWriteFdSet A pointer to the write file descriptors, which may already contain some FDs. + * @param[in,out] aErrorFdSet A pointer to the error file descriptors, which may already contain some FDs. + * @param[in,out] aTimeout A pointer to an initialized timeout. The caller must initialize this to the maximum. + * desired timeout before calling this function; the function may reduce the value, but + * will not increase it. The output should be no larger than the input. + */ +void otSysUpdateEvents(otInstance *aInstance, + int *aMaxFd, + fd_set *aReadFdSet, + fd_set *aWriteFdSet, + fd_set *aErrorFdSet, + struct timeval *aTimeout); + +/** + * Performs all platform-specific processing for OpenThread's example applications. + * + * @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function + * in the main loop when processing OpenThread's drivers is most appropriate. + * @note This should only be called when the fd_set are meaningful, that is, the select() call was successful. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[in] aReadFdSet A pointer to the read file descriptors. + * @param[in] aWriteFdSet A pointer to the write file descriptors. + * @param[in] aErrorFdSet A pointer to the error file descriptors. + */ +void otSysProcessEvents(otInstance *aInstance, + const fd_set *aReadFdSet, + const fd_set *aWriteFdSet, + const fd_set *aErrorFdSet); + +#ifdef __cplusplus +} // end of extern "C" +#endif + +#endif // OPENTHREAD_SELECT_H_ diff --git a/examples/platforms/openthread-system.h b/examples/platforms/openthread-system.h index cde93e96c..b2dec0f96 100644 --- a/examples/platforms/openthread-system.h +++ b/examples/platforms/openthread-system.h @@ -50,7 +50,7 @@ extern "C" { * @param[in] argc Number of arguments in @p argv. * @param[in] argv Argument vector. */ -void otSysInit(int argc, char *argv[]); +void otSysInit(int aArgCount, char *aArgVector[]); /** * Performs all platform-specific deinitialization for OpenThread's drivers. diff --git a/examples/platforms/simulation/platform-config.h b/examples/platforms/simulation/platform-config.h index 9e8638c31..2db6b3ad9 100644 --- a/examples/platforms/simulation/platform-config.h +++ b/examples/platforms/simulation/platform-config.h @@ -40,6 +40,15 @@ #define OPENTHREAD_SIMULATION_UART_BAUDRATE B115200 #endif +/** + * @def OPENTHREAD_SIMULATION_UART_ENABLE + * + * Define as 1 to enable UART transport. + */ +#ifndef OPENTHREAD_SIMULATION_UART_ENABLE +#define OPENTHREAD_SIMULATION_UART_ENABLE 1 +#endif + /** * @def OPENTHREAD_SIMULATION_VIRTUAL_TIME * diff --git a/examples/platforms/simulation/system.c b/examples/platforms/simulation/system.c index 6483a36f6..73caaa743 100644 --- a/examples/platforms/simulation/system.c +++ b/examples/platforms/simulation/system.c @@ -45,12 +45,15 @@ #include #include #include -#include #include +#include +#include + #include #include #include +#include #include "simul_utils.h" @@ -221,67 +224,93 @@ void otSysDeinit(void) void otSysProcessDrivers(otInstance *aInstance) { - fd_set read_fds; - fd_set write_fds; - fd_set error_fds; - int max_fd = -1; + fd_set readFdSet; + fd_set writeFdSet; + fd_set errorFdSet; + int maxFd = -1; struct timeval timeout; - int rval; - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - FD_ZERO(&error_fds); + FD_ZERO(&readFdSet); + FD_ZERO(&writeFdSet); + FD_ZERO(&errorFdSet); - platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd); - platformAlarmUpdateTimeout(&timeout); - platformRadioUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd); + otSysUpdateEvents(aInstance, &maxFd, &readFdSet, &writeFdSet, &errorFdSet, &timeout); + + if (select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, &timeout) < 0) + { + if (errno != EINTR) + { + perror("select"); + exit(EXIT_FAILURE); + } + + FD_ZERO(&readFdSet); + FD_ZERO(&writeFdSet); + FD_ZERO(&errorFdSet); + } + + otSysProcessEvents(aInstance, &readFdSet, &writeFdSet, &errorFdSet); +} + +void otSysUpdateEvents(otInstance *aInstance, + int *aMaxFd, + fd_set *aReadFdSet, + fd_set *aWriteFdSet, + fd_set *aErrorFdSet, + struct timeval *aTimeout) +{ + OT_UNUSED_VARIABLE(aErrorFdSet); + +#if OPENTHREAD_SIMULATION_UART_ENABLE + platformUartUpdateFdSet(aReadFdSet, aWriteFdSet, aErrorFdSet, aMaxFd); +#endif + platformAlarmUpdateTimeout(aTimeout); + platformRadioUpdateFdSet(aReadFdSet, aWriteFdSet, aTimeout, aMaxFd); #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE - platformTrelUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd); + platformTrelUpdateFdSet(aReadFdSet, aWriteFdSet, aTimeout, aMaxFd); #endif #if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE - platformInfraIfUpdateFdSet(&read_fds, &write_fds, &max_fd); + platformInfraIfUpdateFdSet(aReadFdSet, aWriteFdSet, aMaxFd); #endif #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_SIMULATION_MDNS_SOCKET_IMPLEMENT_POSIX - platformMdnsSocketUpdateFdSet(&read_fds, &max_fd); + platformMdnsSocketUpdateFdSet(aReadFdSet, aMaxFd); #endif #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE - platformBleUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd); + platformBleUpdateFdSet(aReadFdSet, aWriteFdSet, aTimeout, aMaxFd); #endif - if (otTaskletsArePending(aInstance)) { - timeout.tv_sec = 0; - timeout.tv_usec = 0; + aTimeout->tv_sec = 0; + aTimeout->tv_usec = 0; } +} - rval = select(max_fd + 1, &read_fds, &write_fds, &error_fds, &timeout); +void otSysProcessEvents(otInstance *aInstance, + const fd_set *aReadFdSet, + const fd_set *aWriteFdSet, + const fd_set *aErrorFdSet) +{ + OT_UNUSED_VARIABLE(aErrorFdSet); - if (rval >= 0) - { - platformUartProcess(); - platformRadioProcess(aInstance, &read_fds, &write_fds); -#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE - platformBleProcess(aInstance, &read_fds, &write_fds); +#if OPENTHREAD_SIMULATION_UART_ENABLE + platformUartProcess(); +#endif + platformRadioProcess(aInstance, aReadFdSet, aWriteFdSet); +#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE + platformBleProcess(aInstance, aReadFdSet, aWriteFdSet); #endif - } - else if (errno != EINTR) - { - perror("select"); - exit(EXIT_FAILURE); - } platformAlarmProcess(aInstance); #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE - platformTrelProcess(aInstance, &read_fds, &write_fds); + platformTrelProcess(aInstance, aReadFdSet, aWriteFdSet); #endif #if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE - platformInfraIfProcess(aInstance, &read_fds, &write_fds); + platformInfraIfProcess(aInstance, aReadFdSet, aWriteFdSet); #endif #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_SIMULATION_MDNS_SOCKET_IMPLEMENT_POSIX - platformMdnsSocketProcess(aInstance, &read_fds); + platformMdnsSocketProcess(aInstance, aReadFdSet); #endif - if (gTerminate) { exit(0);