mirror of
https://github.com/espressif/openthread.git
synced 2026-09-03 15:50:06 +00:00
[radio-spinel] parse frame rx timestamp (#3731)
This commit parses rx timestamp of radio frame received by RCP, no matter data frames or ACK frames. * add OT_NUM_ERRORS as number of defined errors. * allow empty SPINEL_DATATYPE_DATA and SPINEL_DATATYPE_DATA_WLEN when parsing spinel packets.
This commit is contained in:
@@ -347,6 +347,11 @@ typedef enum otError
|
||||
*/
|
||||
OT_ERROR_LINK_MARGIN_LOW = 34,
|
||||
|
||||
/**
|
||||
* The number of defined errors.
|
||||
*/
|
||||
OT_NUM_ERRORS,
|
||||
|
||||
/**
|
||||
* Generic error (should not use).
|
||||
*/
|
||||
|
||||
@@ -61,14 +61,18 @@ void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError)
|
||||
uint16_t flags = 0;
|
||||
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
|
||||
|
||||
// Append frame header and frame length
|
||||
// Append frame header
|
||||
SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW));
|
||||
SuccessOrExit(mEncoder.WriteUint16((aError == OT_ERROR_NONE) ? aFrame->mLength : 0));
|
||||
|
||||
if (aError == OT_ERROR_NONE)
|
||||
{
|
||||
// Append the frame contents
|
||||
SuccessOrExit(mEncoder.WriteData(aFrame->mPsdu, aFrame->mLength));
|
||||
SuccessOrExit(mEncoder.WriteDataWithLen(aFrame->mPsdu, aFrame->mLength));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Append length
|
||||
SuccessOrExit(mEncoder.WriteUint16(0));
|
||||
}
|
||||
|
||||
// Append metadata (rssi, etc)
|
||||
@@ -123,11 +127,17 @@ void NcpBase::LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame,
|
||||
SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise Floor (Currently unused)
|
||||
SuccessOrExit(mEncoder.WriteUint16(0)); // Flags
|
||||
|
||||
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
|
||||
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
|
||||
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mChannel)); // Receive channel
|
||||
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mInfo.mRxInfo.mLqi)); // Link Quality Indicator
|
||||
SuccessOrExit(mEncoder.WriteUint32(aAckFrame->mInfo.mRxInfo.mMsec)); // The timestamp milliseconds
|
||||
SuccessOrExit(
|
||||
mEncoder.WriteUint16(aAckFrame->mInfo.mRxInfo.mUsec)); // The timestamp microseconds, offset to mMsec
|
||||
|
||||
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mChannel)); // Receive channel
|
||||
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mInfo.mRxInfo.mLqi)); // Link Quality Indicator
|
||||
SuccessOrExit(mEncoder.CloseStruct());
|
||||
|
||||
SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data
|
||||
SuccessOrExit(mEncoder.WriteUintPacked(aError)); // Receive error
|
||||
SuccessOrExit(mEncoder.CloseStruct());
|
||||
}
|
||||
|
||||
|
||||
@@ -601,27 +601,45 @@ exit:
|
||||
otError RadioSpinel::ParseRadioFrame(otRadioFrame &aFrame, const uint8_t *aBuffer, uint16_t aLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t packetLength = 0;
|
||||
uint16_t flags = 0;
|
||||
int8_t noiseFloor = -128;
|
||||
spinel_size_t size = OT_RADIO_FRAME_MAX_SIZE;
|
||||
unsigned int receiveError = 0;
|
||||
spinel_ssize_t unpacked;
|
||||
uint16_t flags = 0;
|
||||
int8_t noiseFloor = -128;
|
||||
spinel_size_t size = OT_RADIO_FRAME_MAX_SIZE;
|
||||
|
||||
unpacked = spinel_datatype_unpack(aBuffer, aLength, SPINEL_DATATYPE_UINT16_S, &packetLength);
|
||||
VerifyOrExit(unpacked > 0 && packetLength <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_PARSE);
|
||||
// Timestamp is ms + us.
|
||||
unpacked = spinel_datatype_unpack_in_place(
|
||||
aBuffer, aLength,
|
||||
SPINEL_DATATYPE_DATA_WLEN_S // Frame
|
||||
SPINEL_DATATYPE_INT8_S // RSSI
|
||||
SPINEL_DATATYPE_INT8_S // Noise Floor
|
||||
SPINEL_DATATYPE_UINT16_S // Flags
|
||||
SPINEL_DATATYPE_STRUCT_S( // PHY-data
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 channel
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI
|
||||
SPINEL_DATATYPE_UINT32_S // Timestamp (ms).
|
||||
SPINEL_DATATYPE_UINT16_S // Timestamp (us).
|
||||
) SPINEL_DATATYPE_STRUCT_S( // Vendor-data
|
||||
SPINEL_DATATYPE_UINT_PACKED_S // Receive error
|
||||
),
|
||||
aFrame.mPsdu, &size, &aFrame.mInfo.mRxInfo.mRssi, &noiseFloor, &flags, &aFrame.mChannel,
|
||||
&aFrame.mInfo.mRxInfo.mLqi, &aFrame.mInfo.mRxInfo.mMsec, &aFrame.mInfo.mRxInfo.mUsec, &receiveError);
|
||||
|
||||
aFrame.mLength = static_cast<uint8_t>(packetLength);
|
||||
|
||||
unpacked = spinel_datatype_unpack_in_place(aBuffer, aLength,
|
||||
SPINEL_DATATYPE_DATA_WLEN_S SPINEL_DATATYPE_INT8_S SPINEL_DATATYPE_INT8_S
|
||||
SPINEL_DATATYPE_UINT16_S SPINEL_DATATYPE_STRUCT_S( // PHY-data
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 channel
|
||||
SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI
|
||||
),
|
||||
aFrame.mPsdu, &size, &aFrame.mInfo.mRxInfo.mRssi, &noiseFloor, &flags,
|
||||
&aFrame.mChannel, &aFrame.mInfo.mRxInfo.mLqi);
|
||||
VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE);
|
||||
|
||||
if (receiveError == OT_ERROR_NONE)
|
||||
{
|
||||
aFrame.mLength = static_cast<uint8_t>(size);
|
||||
}
|
||||
else if (receiveError < OT_NUM_ERRORS)
|
||||
{
|
||||
error = static_cast<otError>(receiveError);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_PARSE;
|
||||
}
|
||||
|
||||
exit:
|
||||
LogIfFail("Handle radio frame failed", error);
|
||||
return error;
|
||||
|
||||
Reference in New Issue
Block a user