mirror of
https://github.com/espressif/openthread.git
synced 2026-08-11 21:27:46 +00:00
[posix-app] optimize the interface between radio_spinel and hdlc_interface (#4352)
This commit simplifies the API between RadioSpinel and HdlcInterface to improve extensibility of the API so that we can easily add other low layer interfaces to send/receive spinel frames later. RadioSpinel is only responsible for encoding/decoding spinel frames. Lower layer interface is only responsible for sending/receiving spinel frames. Some lower layer interfaces can't provide a file descriptor for RadioSpinel to wait for the file descriptor to become writable, so this commit removes the kStateTransmitPending state from RadioSpinel.c and directly calls the function Request() to send frames in method RadioSpinel::Transmit().
This commit is contained in:
committed by
Jonathan Hui
parent
4a4a1a349f
commit
7fdd85b687
@@ -247,6 +247,94 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError HdlcInterface::WaitForFrame(struct timeval &aTimeout)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
struct Event event;
|
||||
|
||||
platformSimSendSleepEvent(&aTimeout);
|
||||
platformSimReceiveEvent(&event);
|
||||
|
||||
switch (event.mEvent)
|
||||
{
|
||||
case OT_SIM_EVENT_RADIO_SPINEL_WRITE:
|
||||
Decode(event.mData, event.mDataLength);
|
||||
break;
|
||||
|
||||
case OT_SIM_EVENT_ALARM_FIRED:
|
||||
ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
#else // OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
fd_set read_fds;
|
||||
fd_set error_fds;
|
||||
int rval;
|
||||
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
FD_SET(mSockFd, &read_fds);
|
||||
FD_SET(mSockFd, &error_fds);
|
||||
|
||||
rval = select(mSockFd + 1, &read_fds, NULL, &error_fds, &aTimeout);
|
||||
|
||||
if (rval > 0)
|
||||
{
|
||||
if (FD_ISSET(mSockFd, &read_fds))
|
||||
{
|
||||
Read();
|
||||
}
|
||||
else if (FD_ISSET(mSockFd, &error_fds))
|
||||
{
|
||||
DieNowWithMessage("NCP error", OT_EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DieNow(OT_EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else if (rval == 0)
|
||||
{
|
||||
ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
DieNowWithMessage("wait response", OT_EXIT_FAILURE);
|
||||
}
|
||||
#endif // OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void HdlcInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aWriteFdSet);
|
||||
OT_UNUSED_VARIABLE(aTimeout);
|
||||
|
||||
FD_SET(mSockFd, &aReadFdSet);
|
||||
|
||||
if (aMaxFd < mSockFd)
|
||||
{
|
||||
aMaxFd = mSockFd;
|
||||
}
|
||||
}
|
||||
|
||||
void HdlcInterface::Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aWriteFdSet);
|
||||
|
||||
if (FD_ISSET(mSockFd, &aReadFdSet))
|
||||
{
|
||||
Read();
|
||||
}
|
||||
}
|
||||
|
||||
otError HdlcInterface::WaitForWritable(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -120,24 +120,6 @@ public:
|
||||
*/
|
||||
void Deinit(void);
|
||||
|
||||
/**
|
||||
*
|
||||
* This method returns the socket file descriptor associated with the interface.
|
||||
*
|
||||
* @returns The associated socket file descriptor, or -1 if interface is not initializes.
|
||||
*
|
||||
*/
|
||||
int GetSocket(void) const { return mSockFd; }
|
||||
|
||||
/**
|
||||
* This method instructs `HdlcInterface` to read and decode data from radio over the socket.
|
||||
*
|
||||
* If a full HDLC frame is decoded while reading data, this method invokes the `HandleReceivedFrame()` (on the
|
||||
* `aCallback` object from constructor) to pass the received frame to be processed.
|
||||
*
|
||||
*/
|
||||
void Read(void);
|
||||
|
||||
/**
|
||||
* This method gets the `RxFrameBuffer`.
|
||||
*
|
||||
@@ -170,6 +152,37 @@ public:
|
||||
*/
|
||||
otError SendFrame(const uint8_t *aFrame, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* This method waits for receiving part or all of spinel frame within specified interval.
|
||||
*
|
||||
* @param[in] aTimeout A reference to the timeout.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Part or all of spinel frame is received.
|
||||
* @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout.
|
||||
*
|
||||
*/
|
||||
otError WaitForFrame(struct timeval &aTimeout);
|
||||
|
||||
/**
|
||||
* This method updates the file descriptor sets with file descriptors used by the radio driver.
|
||||
*
|
||||
* @param[inout] aReadFdSet A reference to the read file descriptors.
|
||||
* @param[inout] aWriteFdSet A reference to the write file descriptors.
|
||||
* @param[inout] aMaxFd A reference to the max file descriptor.
|
||||
* @param[inout] aTimeout A reference to the timeout.
|
||||
*
|
||||
*/
|
||||
void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout);
|
||||
|
||||
/**
|
||||
* This method performs radio driver processing.
|
||||
*
|
||||
* @param[in] aReadFdSet A reference to the read file descriptors.
|
||||
* @param[in] aWriteFdSet A reference to the write file descriptors.
|
||||
*
|
||||
*/
|
||||
void Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet);
|
||||
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
/**
|
||||
* This method process read data (decode the data).
|
||||
@@ -185,6 +198,15 @@ public:
|
||||
#endif
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method instructs `HdlcInterface` to read and decode data from radio over the socket.
|
||||
*
|
||||
* If a full HDLC frame is decoded while reading data, this method invokes the `HandleReceivedFrame()` (on the
|
||||
* `aCallback` object from constructor) to pass the received frame to be processed.
|
||||
*
|
||||
*/
|
||||
void Read(void);
|
||||
|
||||
/**
|
||||
* This method waits for the socket file descriptor associated with the HDLC interface to become writable within
|
||||
* `kMaxWaitTime` interval.
|
||||
|
||||
@@ -369,15 +369,6 @@ void platformSimReceiveEvent(struct Event *aEvent);
|
||||
*/
|
||||
void platformSimSendSleepEvent(const struct timeval *aTimeout);
|
||||
|
||||
/**
|
||||
* This function updates the file descriptor sets with file descriptors
|
||||
* used by radio spinel of virtual time simulation.
|
||||
*
|
||||
* @param[out] aTimeout A pointer to the timeout event to be updated.
|
||||
*
|
||||
*/
|
||||
void platformSimRadioSpinelUpdate(struct timeval *atimeout);
|
||||
|
||||
/**
|
||||
* This function performs radio spinel processing of virtual time simulation.
|
||||
*
|
||||
|
||||
@@ -681,7 +681,6 @@ void RadioSpinel::RadioReceive(void)
|
||||
ExitNow();
|
||||
|
||||
case kStateReceive:
|
||||
case kStateTransmitPending:
|
||||
case kStateTransmitting:
|
||||
case kStateTransmitDone:
|
||||
break;
|
||||
@@ -703,22 +702,25 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RadioSpinel::TransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(mInstance, aFrame, aError);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(mInstance, aFrame, aAckFrame, aError);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioSpinel::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout)
|
||||
{
|
||||
int sockFd = mHdlcInterface.GetSocket();
|
||||
mHdlcInterface.UpdateFdSet(aReadFdSet, aWriteFdSet, aMaxFd, aTimeout);
|
||||
|
||||
FD_SET(sockFd, &aReadFdSet);
|
||||
|
||||
if (aMaxFd < sockFd)
|
||||
{
|
||||
aMaxFd = sockFd;
|
||||
}
|
||||
|
||||
if (mState == kStateTransmitPending)
|
||||
{
|
||||
FD_SET(sockFd, &aWriteFdSet);
|
||||
}
|
||||
else if (mState == kStateTransmitting)
|
||||
if (mState == kStateTransmitting)
|
||||
{
|
||||
uint64_t now = platformGetTime();
|
||||
|
||||
@@ -754,9 +756,10 @@ void RadioSpinel::Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet)
|
||||
ProcessFrameQueue();
|
||||
}
|
||||
|
||||
if (FD_ISSET(mHdlcInterface.GetSocket(), &aReadFdSet))
|
||||
mHdlcInterface.Process(aReadFdSet, aWriteFdSet);
|
||||
|
||||
if (mHdlcInterface.GetRxFrameBuffer().HasSavedFrame())
|
||||
{
|
||||
mHdlcInterface.Read();
|
||||
ProcessFrameQueue();
|
||||
}
|
||||
|
||||
@@ -765,30 +768,13 @@ void RadioSpinel::Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet)
|
||||
mState = kStateReceive;
|
||||
mTxRadioEndUs = UINT64_MAX;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(mInstance, mTransmitFrame, mTxError);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(mInstance, mTransmitFrame, (mAckRadioFrame.mLength != 0) ? &mAckRadioFrame : NULL,
|
||||
mTxError);
|
||||
}
|
||||
TransmitDone(mTransmitFrame, (mAckRadioFrame.mLength != 0) ? &mAckRadioFrame : NULL, mTxError);
|
||||
}
|
||||
else if (mState == kStateTransmitting && platformGetTime() >= mTxRadioEndUs)
|
||||
{
|
||||
// Frame has been successfully passed to radio, but no `TransmitDone` event received within TX_WAIT_US.
|
||||
DieNowWithMessage("radio tx timeout", OT_EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (FD_ISSET(mHdlcInterface.GetSocket(), &aWriteFdSet))
|
||||
{
|
||||
if (mState == kStateTransmitPending)
|
||||
{
|
||||
RadioTransmit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
otError RadioSpinel::SetPromiscuous(bool aEnable)
|
||||
@@ -1054,68 +1040,12 @@ otError RadioSpinel::WaitResponse(void)
|
||||
|
||||
do
|
||||
{
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
struct Event event;
|
||||
|
||||
platformSimSendSleepEvent(&timeout);
|
||||
platformSimReceiveEvent(&event);
|
||||
|
||||
switch (event.mEvent)
|
||||
{
|
||||
case OT_SIM_EVENT_RADIO_SPINEL_WRITE:
|
||||
mHdlcInterface.ProcessReadData(event.mData, event.mDataLength);
|
||||
break;
|
||||
|
||||
case OT_SIM_EVENT_ALARM_FIRED:
|
||||
FreeTid(mWaitingTid);
|
||||
mWaitingTid = 0;
|
||||
ExitNow(mError = OT_ERROR_RESPONSE_TIMEOUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
#else // OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
int sockFd = mHdlcInterface.GetSocket();
|
||||
fd_set read_fds;
|
||||
fd_set error_fds;
|
||||
int rval;
|
||||
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
FD_SET(sockFd, &read_fds);
|
||||
FD_SET(sockFd, &error_fds);
|
||||
|
||||
rval = select(sockFd + 1, &read_fds, NULL, &error_fds, &timeout);
|
||||
|
||||
if (rval > 0)
|
||||
{
|
||||
if (FD_ISSET(sockFd, &read_fds))
|
||||
{
|
||||
mHdlcInterface.Read();
|
||||
}
|
||||
else if (FD_ISSET(sockFd, &error_fds))
|
||||
{
|
||||
DieNowWithMessage("NCP error", OT_EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
DieNow(OT_EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else if (rval == 0)
|
||||
if (mHdlcInterface.WaitForFrame(timeout) == OT_ERROR_RESPONSE_TIMEOUT)
|
||||
{
|
||||
FreeTid(mWaitingTid);
|
||||
mWaitingTid = 0;
|
||||
ExitNow(mError = OT_ERROR_RESPONSE_TIMEOUT);
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
DieNowWithMessage("wait response", OT_EXIT_FAILURE);
|
||||
}
|
||||
#endif // OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
|
||||
now = platformGetTime();
|
||||
|
||||
@@ -1154,53 +1084,6 @@ spinel_tid_t RadioSpinel::GetNextTid(void)
|
||||
return tid;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method delivers the radio frame to transceiver.
|
||||
*
|
||||
* otPlatRadioTxStarted() is triggered immediately for now, which may be earlier than real started time.
|
||||
*
|
||||
*/
|
||||
void RadioSpinel::RadioTransmit(void)
|
||||
{
|
||||
otError error;
|
||||
|
||||
assert(mTransmitFrame != NULL);
|
||||
otPlatRadioTxStarted(mInstance, mTransmitFrame);
|
||||
assert(mState == kStateTransmitPending);
|
||||
|
||||
error = Request(true, SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_STREAM_RAW,
|
||||
SPINEL_DATATYPE_DATA_WLEN_S // Frame data
|
||||
SPINEL_DATATYPE_UINT8_S // Channel
|
||||
SPINEL_DATATYPE_UINT8_S // MaxCsmaBackoffs
|
||||
SPINEL_DATATYPE_UINT8_S // MaxFrameRetries
|
||||
SPINEL_DATATYPE_BOOL_S, // CsmaCaEnabled
|
||||
mTransmitFrame->mPsdu, mTransmitFrame->mLength, mTransmitFrame->mChannel,
|
||||
mTransmitFrame->mInfo.mTxInfo.mMaxCsmaBackoffs, mTransmitFrame->mInfo.mTxInfo.mMaxFrameRetries,
|
||||
mTransmitFrame->mInfo.mTxInfo.mCsmaCaEnabled);
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
mTxRadioEndUs = platformGetTime() + TX_WAIT_US;
|
||||
mState = kStateTransmitting;
|
||||
}
|
||||
else
|
||||
{
|
||||
mState = kStateReceive;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(mInstance, mTransmitFrame, error);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(mInstance, mTransmitFrame, NULL, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
otError RadioSpinel::SendReset(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -1344,10 +1227,29 @@ otError RadioSpinel::Transmit(otRadioFrame &aFrame)
|
||||
otError error = OT_ERROR_INVALID_STATE;
|
||||
|
||||
VerifyOrExit(mState == kStateReceive);
|
||||
mState = kStateTransmitPending;
|
||||
error = OT_ERROR_NONE;
|
||||
|
||||
mTransmitFrame = &aFrame;
|
||||
|
||||
// `otPlatRadioTxStarted()` is triggered immediately for now, which may be earlier than real started time.
|
||||
otPlatRadioTxStarted(mInstance, mTransmitFrame);
|
||||
|
||||
error = Request(true, SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_STREAM_RAW,
|
||||
SPINEL_DATATYPE_DATA_WLEN_S // Frame data
|
||||
SPINEL_DATATYPE_UINT8_S // Channel
|
||||
SPINEL_DATATYPE_UINT8_S // MaxCsmaBackoffs
|
||||
SPINEL_DATATYPE_UINT8_S // MaxFrameRetries
|
||||
SPINEL_DATATYPE_BOOL_S, // CsmaCaEnabled
|
||||
mTransmitFrame->mPsdu, mTransmitFrame->mLength, mTransmitFrame->mChannel,
|
||||
mTransmitFrame->mInfo.mTxInfo.mMaxCsmaBackoffs, mTransmitFrame->mInfo.mTxInfo.mMaxFrameRetries,
|
||||
mTransmitFrame->mInfo.mTxInfo.mCsmaCaEnabled);
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
// Waiting for `TransmitDone` event.
|
||||
mState = kStateTransmitting;
|
||||
mTxRadioEndUs = platformGetTime() + TX_WAIT_US;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -1755,47 +1657,27 @@ void ot::PosixApp::RadioSpinel::Process(const Event &aEvent)
|
||||
if (aEvent.mEvent == OT_SIM_EVENT_RADIO_SPINEL_WRITE)
|
||||
{
|
||||
mHdlcInterface.ProcessReadData(aEvent.mData, aEvent.mDataLength);
|
||||
}
|
||||
|
||||
if (mHdlcInterface.GetRxFrameBuffer().HasSavedFrame())
|
||||
{
|
||||
ProcessFrameQueue();
|
||||
}
|
||||
|
||||
if (mState == kStateTransmitDone)
|
||||
{
|
||||
mState = kStateReceive;
|
||||
mState = kStateReceive;
|
||||
mTxRadioEndUs = UINT64_MAX;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(mInstance, mTransmitFrame, mTxError);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(mInstance, mTransmitFrame, (mAckRadioFrame.mLength != 0) ? &mAckRadioFrame : NULL,
|
||||
mTxError);
|
||||
}
|
||||
TransmitDone(mTransmitFrame, (mAckRadioFrame.mLength != 0) ? &mAckRadioFrame : NULL, mTxError);
|
||||
}
|
||||
|
||||
if (mState == kStateTransmitPending)
|
||||
else if (mState == kStateTransmitting && platformGetTime() >= mTxRadioEndUs)
|
||||
{
|
||||
RadioTransmit();
|
||||
// Frame has been successfully passed to radio, but no `TransmitDone` event received within TX_WAIT_US.
|
||||
DieNowWithMessage("radio tx timeout", OT_EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void ot::PosixApp::RadioSpinel::Update(struct timeval &aTimeout)
|
||||
{
|
||||
// Prevent sleep event when transmitting
|
||||
if (mState == kStateTransmitPending)
|
||||
{
|
||||
aTimeout.tv_sec = 0;
|
||||
aTimeout.tv_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void platformSimRadioSpinelUpdate(struct timeval *aTimeout)
|
||||
{
|
||||
sRadioSpinel.Update(*aTimeout);
|
||||
}
|
||||
|
||||
void platformSimRadioSpinelProcess(otInstance *aInstance, const struct Event *aEvent)
|
||||
{
|
||||
sRadioSpinel.Process(*aEvent);
|
||||
|
||||
@@ -531,12 +531,11 @@ private:
|
||||
|
||||
enum State
|
||||
{
|
||||
kStateDisabled, ///< Radio is disabled.
|
||||
kStateSleep, ///< Radio is sleep.
|
||||
kStateReceive, ///< Radio is in receive mode.
|
||||
kStateTransmitPending, ///< Frame transmission requested, waiting to pass frame to radio.
|
||||
kStateTransmitting, ///< Frame passed to radio for transmission, waiting for done event from radio.
|
||||
kStateTransmitDone, ///< Radio indicated frame transmission is done.
|
||||
kStateDisabled, ///< Radio is disabled.
|
||||
kStateSleep, ///< Radio is sleep.
|
||||
kStateReceive, ///< Radio is in receive mode.
|
||||
kStateTransmitting, ///< Frame passed to radio for transmission, waiting for done event from radio.
|
||||
kStateTransmitDone, ///< Radio indicated frame transmission is done.
|
||||
};
|
||||
|
||||
otError CheckSpinelVersion(void);
|
||||
@@ -640,7 +639,8 @@ private:
|
||||
void HandleWaitingResponse(uint32_t aCommand, spinel_prop_key_t aKey, const uint8_t *aBuffer, uint16_t aLength);
|
||||
|
||||
void RadioReceive(void);
|
||||
void RadioTransmit(void);
|
||||
|
||||
void TransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
|
||||
|
||||
otInstance *mInstance;
|
||||
|
||||
|
||||
@@ -171,14 +171,13 @@ void platformSimUpdateFdSet(fd_set * aReadFdSet,
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aWriteFdSet);
|
||||
OT_UNUSED_VARIABLE(aErrorFdSet);
|
||||
OT_UNUSED_VARIABLE(aTimeout);
|
||||
|
||||
FD_SET(sSockFd, aReadFdSet);
|
||||
if (*aMaxFd < sSockFd)
|
||||
{
|
||||
*aMaxFd = sSockFd;
|
||||
}
|
||||
|
||||
platformSimRadioSpinelUpdate(aTimeout);
|
||||
}
|
||||
|
||||
void platformSimProcess(otInstance * aInstance,
|
||||
|
||||
Reference in New Issue
Block a user