[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:
Yakun Xu
2019-04-07 21:34:40 -07:00
committed by Jonathan Hui
parent 7c3bce3a4f
commit 174d076722
3 changed files with 55 additions and 22 deletions
+5
View File
@@ -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).
*/
+16 -6
View File
@@ -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());
}
+34 -16
View File
@@ -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;