#include "openthread-posix-config.h"
#include "platform-posix.h"
#include <assert.h>
#include <openthread-core-config.h>
#include <openthread/tasklet.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/uart.h>
#include "common/code_utils.hpp"
uint64_t gNodeId = 0;
otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
{
otInstance * instance = NULL;
ot::Posix::Arguments args(aPlatformConfig->mRadioUrl);
#if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeInit(static_cast<uint16_t>(atoi(args.GetValue("arg"))));
#endif
VerifyOrDie(args.GetPath() != NULL, OT_EXIT_INVALID_ARGUMENTS);
platformAlarmInit(aPlatformConfig->mSpeedUpFactor);
platformRadioInit(&args);
platformRandomInit();
instance = otInstanceInitSingle();
assert(instance != NULL);
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
platformNetifInit(instance, aPlatformConfig->mInterfaceName);
#elif OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
platformUdpInit(aPlatformConfig->mInterfaceName);
#endif
return instance;
}
void otSysDeinit(void)
{
#if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeDeinit();
#endif
platformRadioDeinit();
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
platformNetifDeinit();
#endif
IgnoreError(otPlatUartDisable());
}
#if OPENTHREAD_POSIX_VIRTUAL_TIME
static int trySelect(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int aMaxFd)
{
struct timeval timeout = {0, 0};
fd_set originReadFdSet = *aReadFdSet;
fd_set originWriteFdSet = *aWriteFdSet;
fd_set originErrorFdSet = *aErrorFdSet;
int rval;
rval = select(aMaxFd + 1, aReadFdSet, aWriteFdSet, aErrorFdSet, &timeout);
if (rval == 0)
{
*aReadFdSet = originReadFdSet;
*aWriteFdSet = originWriteFdSet;
*aErrorFdSet = originErrorFdSet;
}
return rval;
}
#endif
void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop)
{
platformAlarmUpdateTimeout(&aMainloop->mTimeout);
platformUartUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
&aMainloop->mMaxFd);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
platformUdpUpdateFdSet(aInstance, &aMainloop->mReadFdSet, &aMainloop->mMaxFd);
#endif
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
platformNetifUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
&aMainloop->mMaxFd);
#endif
#if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, &aMainloop->mMaxFd,
&aMainloop->mTimeout);
#else
platformRadioUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mMaxFd, &aMainloop->mTimeout);
#endif
if (otTaskletsArePending(aInstance))
{
aMainloop->mTimeout.tv_sec = 0;
aMainloop->mTimeout.tv_usec = 0;
}
}
int otSysMainloopPoll(otSysMainloopContext *aMainloop)
{
int rval;
#if OPENTHREAD_POSIX_VIRTUAL_TIME
if (timerisset(&aMainloop->mTimeout))
{
rval = trySelect(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, aMainloop->mMaxFd);
if (rval == 0)
{
bool noWrite = true;
for (int i = 0; i < aMainloop->mMaxFd + 1; ++i)
{
if (FD_ISSET(i, &aMainloop->mWriteFdSet))
{
noWrite = false;
break;
}
}
if (noWrite)
{
virtualTimeSendSleepEvent(&aMainloop->mTimeout);
}
rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet,
&aMainloop->mErrorFdSet, NULL);
}
}
else
#endif
{
rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
&aMainloop->mTimeout);
}
return rval;
}
void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop)
{
#if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
#else
platformRadioProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet);
#endif
platformUartProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
platformAlarmProcess(aInstance);
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
platformNetifProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
#endif
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
platformUdpProcess(aInstance, &aMainloop->mReadFdSet);
#endif
}