From 3d4f617a00e63d09bedbe57cb042ebad74c023f0 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Wed, 9 Nov 2022 18:40:14 +0800 Subject: [PATCH] [spinel] log radio spinel frame (#8342) --- src/lib/spinel/radio_spinel.hpp | 3 + src/lib/spinel/radio_spinel_impl.hpp | 594 ++++++++++++++++++++++++++- src/lib/spinel/spinel.c | 2 + src/lib/spinel/spinel.h | 3 + 4 files changed, 601 insertions(+), 1 deletion(-) diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp index b0d3b463f..2f15d0378 100644 --- a/src/lib/spinel/radio_spinel.hpp +++ b/src/lib/spinel/radio_spinel.hpp @@ -996,6 +996,9 @@ private: mRadioSpinelMetrics.mSpinelParseErrorCount += (aError == OT_ERROR_PARSE) ? 1 : 0; } + uint32_t Snprintf(char *aDest, uint32_t aSize, const char *aFormat, ...); + void LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool aTx); + otInstance *mInstance; SpinelInterface::RxFrameBuffer mRxFrameBuffer; diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp index 21bc3291b..12768290b 100644 --- a/src/lib/spinel/radio_spinel_impl.hpp +++ b/src/lib/spinel/radio_spinel_impl.hpp @@ -461,6 +461,7 @@ void RadioSpinel::HandleReceivedFrame(void) uint8_t header; spinel_ssize_t unpacked; + LogSpinelFrame(mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetLength(), false); unpacked = spinel_datatype_unpack(mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetLength(), "C", &header); VerifyOrExit(unpacked > 0 && (header & SPINEL_HEADER_FLAG) == SPINEL_HEADER_FLAG && @@ -1738,6 +1739,7 @@ otError RadioSpinel::SendReset(uint8_t aReset VerifyOrExit(packed > 0 && static_cast(packed) <= sizeof(buffer), error = OT_ERROR_NO_BUFS); SuccessOrExit(error = mSpinelInterface.SendFrame(buffer, static_cast(packed))); + LogSpinelFrame(buffer, static_cast(packed), true); exit: return error; @@ -1772,7 +1774,8 @@ otError RadioSpinel::SendCommand(uint32_t offset += static_cast(packed); } - error = mSpinelInterface.SendFrame(buffer, offset); + SuccessOrExit(error = mSpinelInterface.SendFrame(buffer, offset)); + LogSpinelFrame(buffer, offset, true); exit: return error; @@ -2510,5 +2513,594 @@ uint8_t RadioSpinel::GetCslUncertainty(void) } #endif +template +uint32_t RadioSpinel::Snprintf(char *aDest, uint32_t aSize, const char *aFormat, ...) +{ + int len; + va_list args; + + va_start(args, aFormat); + len = vsnprintf(aDest, static_cast(aSize), aFormat, args); + va_end(args); + + return (len < 0) ? 0 : (static_cast(len) > aSize - 1 ? aSize - 1 : static_cast(len)); +} + +template +void RadioSpinel::LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool aTx) +{ + otError error = OT_ERROR_NONE; + char buf[OPENTHREAD_CONFIG_LOG_MAX_SIZE] = {0}; + spinel_ssize_t unpacked; + uint8_t header; + uint32_t cmd; + spinel_prop_key_t key; + uint8_t * data; + spinel_size_t len; + const char * prefix = nullptr; + char * start = buf; + char * end = buf + sizeof(buf); + + VerifyOrExit(otLoggingGetLevel() >= OT_LOG_LEVEL_DEBG); + + prefix = aTx ? "Sent spinel frame" : "Received spinel frame"; + unpacked = spinel_datatype_unpack(aFrame, aLength, "CiiD", &header, &cmd, &key, &data, &len); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + start += Snprintf(start, static_cast(end - start), "%s, flg:0x%x, tid:%u, cmd:%s", prefix, + SPINEL_HEADER_GET_FLAG(header), SPINEL_HEADER_GET_TID(header), spinel_command_to_cstr(cmd)); + VerifyOrExit(cmd != SPINEL_CMD_RESET); + + start += Snprintf(start, static_cast(end - start), ", key:%s", spinel_prop_key_to_cstr(key)); + VerifyOrExit(cmd != SPINEL_CMD_PROP_VALUE_GET); + + switch (key) + { + case SPINEL_PROP_LAST_STATUS: + { + spinel_status_t status; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT_PACKED_S, &status); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", status:%s", spinel_status_to_cstr(status)); + } + break; + + case SPINEL_PROP_MAC_RAW_STREAM_ENABLED: + case SPINEL_PROP_MAC_SRC_MATCH_ENABLED: + case SPINEL_PROP_PHY_ENABLED: + case SPINEL_PROP_RADIO_COEX_ENABLE: + { + bool enabled; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_BOOL_S, &enabled); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", enabled:%u", enabled); + } + break; + + case SPINEL_PROP_PHY_CCA_THRESHOLD: + case SPINEL_PROP_PHY_FEM_LNA_GAIN: + case SPINEL_PROP_PHY_RX_SENSITIVITY: + case SPINEL_PROP_PHY_RSSI: + case SPINEL_PROP_PHY_TX_POWER: + { + const char *name = nullptr; + int8_t value; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_INT8_S, &value); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + switch (key) + { + case SPINEL_PROP_PHY_TX_POWER: + name = "power"; + break; + case SPINEL_PROP_PHY_CCA_THRESHOLD: + name = "threshold"; + break; + case SPINEL_PROP_PHY_FEM_LNA_GAIN: + name = "gain"; + break; + case SPINEL_PROP_PHY_RX_SENSITIVITY: + name = "sensitivity"; + break; + case SPINEL_PROP_PHY_RSSI: + name = "rssi"; + break; + } + + start += Snprintf(start, static_cast(end - start), ", %s:%d", name, value); + } + break; + + case SPINEL_PROP_MAC_PROMISCUOUS_MODE: + case SPINEL_PROP_MAC_SCAN_STATE: + case SPINEL_PROP_PHY_CHAN: + case SPINEL_PROP_RCP_CSL_ACCURACY: + case SPINEL_PROP_RCP_CSL_UNCERTAINTY: + { + const char *name = nullptr; + uint8_t value; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT8_S, &value); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + switch (key) + { + case SPINEL_PROP_MAC_SCAN_STATE: + name = "state"; + break; + case SPINEL_PROP_RCP_CSL_ACCURACY: + name = "accuracy"; + break; + case SPINEL_PROP_RCP_CSL_UNCERTAINTY: + name = "uncertainty"; + break; + case SPINEL_PROP_MAC_PROMISCUOUS_MODE: + name = "mode"; + break; + case SPINEL_PROP_PHY_CHAN: + name = "channel"; + break; + } + + start += Snprintf(start, static_cast(end - start), ", %s:%u", name, value); + } + break; + + case SPINEL_PROP_MAC_15_4_PANID: + case SPINEL_PROP_MAC_15_4_SADDR: + case SPINEL_PROP_MAC_SCAN_PERIOD: + case SPINEL_PROP_PHY_REGION_CODE: + { + const char *name = nullptr; + uint16_t value; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT16_S, &value); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + switch (key) + { + case SPINEL_PROP_MAC_SCAN_PERIOD: + name = "period"; + break; + case SPINEL_PROP_PHY_REGION_CODE: + name = "region"; + break; + case SPINEL_PROP_MAC_15_4_SADDR: + name = "saddr"; + break; + case SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES: + name = "saddr"; + break; + case SPINEL_PROP_MAC_15_4_PANID: + name = "panid"; + break; + } + + start += Snprintf(start, static_cast(end - start), ", %s:0x%04x", name, value); + } + break; + + case SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES: + { + uint16_t saddr; + + start += Snprintf(start, static_cast(end - start), ", saddr:"); + + if (len < sizeof(saddr)) + { + start += Snprintf(start, static_cast(end - start), "none"); + } + else + { + while (len >= sizeof(saddr)) + { + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT16_S, &saddr); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + data += unpacked; + len -= static_cast(unpacked); + start += Snprintf(start, static_cast(end - start), "0x%04x ", saddr); + } + } + } + break; + + case SPINEL_PROP_RCP_MAC_FRAME_COUNTER: + case SPINEL_PROP_RCP_TIMESTAMP: + { + const char *name; + uint32_t value; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT32_S, &value); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + name = (key == SPINEL_PROP_RCP_TIMESTAMP) ? "timestamp" : "counter"; + start += Snprintf(start, static_cast(end - start), ", %s:%u", name, value); + } + break; + + case SPINEL_PROP_RADIO_CAPS: + case SPINEL_PROP_RCP_API_VERSION: + { + const char * name; + unsigned int value; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT_PACKED_S, &value); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + name = (key == SPINEL_PROP_RADIO_CAPS) ? "caps" : "version"; + start += Snprintf(start, static_cast(end - start), ", %s:%u", name, value); + } + break; + + case SPINEL_PROP_MAC_ENERGY_SCAN_RESULT: + case SPINEL_PROP_PHY_CHAN_MAX_POWER: + { + const char *name; + uint8_t channel; + int8_t value; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_INT8_S, &channel, &value); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + name = (key == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT) ? "rssi" : "power"; + start += Snprintf(start, static_cast(end - start), ", channel:%u, %s:%d", channel, name, value); + } + break; + + case SPINEL_PROP_CAPS: + { + unsigned int capability; + + start += Snprintf(start, static_cast(end - start), ", caps:"); + + while (len > 0) + { + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT_PACKED_S, &capability); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + data += unpacked; + len -= static_cast(unpacked); + start += Snprintf(start, static_cast(end - start), "%s ", spinel_capability_to_cstr(capability)); + } + } + break; + + case SPINEL_PROP_PROTOCOL_VERSION: + { + unsigned int major; + unsigned int minor; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_UINT_PACKED_S, + &major, &minor); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", major:%u, minor:%u", major, minor); + } + break; + + case SPINEL_PROP_PHY_CHAN_PREFERRED: + case SPINEL_PROP_PHY_CHAN_SUPPORTED: + { + uint8_t maskBuffer[kChannelMaskBufferSize]; + uint32_t channelMask = 0; + const uint8_t *maskData = maskBuffer; + spinel_size_t maskLength = sizeof(maskBuffer); + + unpacked = spinel_datatype_unpack_in_place(data, len, SPINEL_DATATYPE_DATA_S, maskBuffer, &maskLength); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + while (maskLength > 0) + { + uint8_t channel; + + unpacked = spinel_datatype_unpack(maskData, maskLength, SPINEL_DATATYPE_UINT8_S, &channel); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + VerifyOrExit(channel < kChannelMaskBufferSize, error = OT_ERROR_PARSE); + channelMask |= (1UL << channel); + + maskData += unpacked; + maskLength -= static_cast(unpacked); + } + + start += Snprintf(start, static_cast(end - start), ", channelMask:0x%08x", channelMask); + } + break; + + case SPINEL_PROP_NCP_VERSION: + { + const char *version; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UTF8_S, &version); + VerifyOrExit(unpacked >= 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", version:%s", version); + } + break; + + case SPINEL_PROP_STREAM_RAW: + { + otRadioFrame frame; + + if (cmd == SPINEL_CMD_PROP_VALUE_IS) + { + uint16_t flags; + int8_t noiseFloor; + unsigned int receiveError; + + unpacked = spinel_datatype_unpack(data, len, + 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_UINT64_S // Timestamp (us). + ) SPINEL_DATATYPE_STRUCT_S( // Vendor-data + SPINEL_DATATYPE_UINT_PACKED_S // Receive error + ), + &frame.mPsdu, &frame.mLength, &frame.mInfo.mRxInfo.mRssi, &noiseFloor, + &flags, &frame.mChannel, &frame.mInfo.mRxInfo.mLqi, + &frame.mInfo.mRxInfo.mTimestamp, &receiveError); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", len:%u, rssi:%d ...", frame.mLength, + frame.mInfo.mRxInfo.mRssi); + otLogDebgPlat("%s", buf); + + start = buf; + start += Snprintf(start, static_cast(end - start), + "... noise:%d, flags:0x%04x, channel:%u, lqi:%u, timestamp:%lu, rxerr:%u", noiseFloor, + flags, frame.mChannel, frame.mInfo.mRxInfo.mLqi, + static_cast(frame.mInfo.mRxInfo.mTimestamp), receiveError); + } + else if (cmd == SPINEL_CMD_PROP_VALUE_SET) + { + bool csmaCaEnabled; + bool isHeaderUpdated; + bool isARetx; + bool skipAes; + + unpacked = spinel_datatype_unpack( + data, len, + 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 + SPINEL_DATATYPE_BOOL_S // IsHeaderUpdated + SPINEL_DATATYPE_BOOL_S // IsARetx + SPINEL_DATATYPE_BOOL_S // SkipAes + SPINEL_DATATYPE_UINT32_S // TxDelay + SPINEL_DATATYPE_UINT32_S, // TxDelayBaseTime + &frame.mPsdu, &frame.mLength, &frame.mChannel, &frame.mInfo.mTxInfo.mMaxCsmaBackoffs, + &frame.mInfo.mTxInfo.mMaxFrameRetries, &csmaCaEnabled, &isHeaderUpdated, &isARetx, &skipAes, + &frame.mInfo.mTxInfo.mTxDelay, &frame.mInfo.mTxInfo.mTxDelayBaseTime); + + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), + ", len:%u, channel:%u, maxbackoffs:%u, maxretries:%u ...", frame.mLength, frame.mChannel, + frame.mInfo.mTxInfo.mMaxCsmaBackoffs, frame.mInfo.mTxInfo.mMaxFrameRetries); + otLogDebgPlat("%s", buf); + + start = buf; + start += Snprintf(start, static_cast(end - start), + "... csmaCaEnabled:%u, isHeaderUpdated:%u, isARetx:%u, skipAes:%u" + ", txDelay:%u, txDelayBase:%u", + csmaCaEnabled, isHeaderUpdated, isARetx, skipAes, frame.mInfo.mTxInfo.mTxDelay, + frame.mInfo.mTxInfo.mTxDelayBaseTime); + } + } + break; + + case SPINEL_PROP_STREAM_DEBUG: + { + char debugString[OPENTHREAD_CONFIG_NCP_SPINEL_LOG_MAX_SIZE + 1]; + spinel_size_t stringLength = sizeof(debugString); + + unpacked = spinel_datatype_unpack_in_place(data, len, SPINEL_DATATYPE_DATA_S, debugString, &stringLength); + assert(stringLength < sizeof(debugString)); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + debugString[stringLength] = '\0'; + start += Snprintf(start, static_cast(end - start), ", debug:%s", debugString); + } + break; + + case SPINEL_PROP_STREAM_LOG: + { + const char *logString; + uint8_t logLevel; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UTF8_S, &logString); + VerifyOrExit(unpacked >= 0, error = OT_ERROR_PARSE); + data += unpacked; + len -= static_cast(unpacked); + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UINT8_S, &logLevel); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", level:%u, log:%s", logLevel, logString); + } + break; + + case SPINEL_PROP_NEST_STREAM_MFG: + { + const char *output; + size_t outputLen; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_UTF8_S, &output, &outputLen); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", diag:%s", output); + } + break; + + case SPINEL_PROP_RCP_MAC_KEY: + { + uint8_t keyIdMode; + uint8_t keyId; + otMacKey prevKey; + unsigned int prevKeyLen = sizeof(otMacKey); + otMacKey currKey; + unsigned int currKeyLen = sizeof(otMacKey); + otMacKey nextKey; + unsigned int nextKeyLen = sizeof(otMacKey); + + unpacked = spinel_datatype_unpack(data, len, + SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_DATA_WLEN_S + SPINEL_DATATYPE_DATA_WLEN_S SPINEL_DATATYPE_DATA_WLEN_S, + &keyIdMode, &keyId, prevKey.m8, &prevKeyLen, currKey.m8, &currKeyLen, + nextKey.m8, &nextKeyLen); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), + ", keyIdMode:%u, keyId:%u, prevKey:***, currKey:***, nextKey:***", keyIdMode, keyId); + } + break; + + case SPINEL_PROP_HWADDR: + case SPINEL_PROP_MAC_15_4_LADDR: + { + const char *name = nullptr; + uint8_t m8[OT_EXT_ADDRESS_SIZE] = {0}; + + unpacked = spinel_datatype_unpack_in_place(data, len, SPINEL_DATATYPE_EUI64_S, &m8[0]); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + name = (key == SPINEL_PROP_HWADDR) ? "eui64" : "laddr"; + start += Snprintf(start, static_cast(end - start), ", %s:%02x%02x%02x%02x%02x%02x%02x%02x", name, + m8[0], m8[1], m8[2], m8[3], m8[4], m8[5], m8[6], m8[7]); + } + break; + + case SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES: + { + uint8_t m8[OT_EXT_ADDRESS_SIZE]; + + start += Snprintf(start, static_cast(end - start), ", extaddr:"); + + if (len < sizeof(m8)) + { + start += Snprintf(start, static_cast(end - start), "none"); + } + else + { + while (len >= sizeof(m8)) + { + unpacked = spinel_datatype_unpack_in_place(data, len, SPINEL_DATATYPE_EUI64_S, m8); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + data += unpacked; + len -= static_cast(unpacked); + start += Snprintf(start, static_cast(end - start), "%02x%02x%02x%02x%02x%02x%02x%02x ", m8[0], + m8[1], m8[2], m8[3], m8[4], m8[5], m8[6], m8[7]); + } + } + } + break; + + case SPINEL_PROP_RADIO_COEX_METRICS: + { + otRadioCoexMetrics metrics; + unpacked = spinel_datatype_unpack( + data, len, + SPINEL_DATATYPE_STRUCT_S( // Tx Coex Metrics Structure + SPINEL_DATATYPE_UINT32_S // NumTxRequest + SPINEL_DATATYPE_UINT32_S // NumTxGrantImmediate + SPINEL_DATATYPE_UINT32_S // NumTxGrantWait + SPINEL_DATATYPE_UINT32_S // NumTxGrantWaitActivated + SPINEL_DATATYPE_UINT32_S // NumTxGrantWaitTimeout + SPINEL_DATATYPE_UINT32_S // NumTxGrantDeactivatedDuringRequest + SPINEL_DATATYPE_UINT32_S // NumTxDelayedGrant + SPINEL_DATATYPE_UINT32_S // AvgTxRequestToGrantTime + ) SPINEL_DATATYPE_STRUCT_S( // Rx Coex Metrics Structure + SPINEL_DATATYPE_UINT32_S // NumRxRequest + SPINEL_DATATYPE_UINT32_S // NumRxGrantImmediate + SPINEL_DATATYPE_UINT32_S // NumRxGrantWait + SPINEL_DATATYPE_UINT32_S // NumRxGrantWaitActivated + SPINEL_DATATYPE_UINT32_S // NumRxGrantWaitTimeout + SPINEL_DATATYPE_UINT32_S // NumRxGrantDeactivatedDuringRequest + SPINEL_DATATYPE_UINT32_S // NumRxDelayedGrant + SPINEL_DATATYPE_UINT32_S // AvgRxRequestToGrantTime + SPINEL_DATATYPE_UINT32_S // NumRxGrantNone + ) SPINEL_DATATYPE_BOOL_S // Stopped + SPINEL_DATATYPE_UINT32_S, // NumGrantGlitch + &metrics.mNumTxRequest, &metrics.mNumTxGrantImmediate, &metrics.mNumTxGrantWait, + &metrics.mNumTxGrantWaitActivated, &metrics.mNumTxGrantWaitTimeout, + &metrics.mNumTxGrantDeactivatedDuringRequest, &metrics.mNumTxDelayedGrant, + &metrics.mAvgTxRequestToGrantTime, &metrics.mNumRxRequest, &metrics.mNumRxGrantImmediate, + &metrics.mNumRxGrantWait, &metrics.mNumRxGrantWaitActivated, &metrics.mNumRxGrantWaitTimeout, + &metrics.mNumRxGrantDeactivatedDuringRequest, &metrics.mNumRxDelayedGrant, + &metrics.mAvgRxRequestToGrantTime, &metrics.mNumRxGrantNone, &metrics.mStopped, &metrics.mNumGrantGlitch); + + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + + otLogDebgPlat("%s ...", buf); + otLogDebgPlat(" txRequest:%u", metrics.mNumTxRequest); + otLogDebgPlat(" txGrantImmediate:%u", metrics.mNumTxGrantImmediate); + otLogDebgPlat(" txGrantWait:%u", metrics.mNumTxGrantWait); + otLogDebgPlat(" txGrantWaitActivated:%u", metrics.mNumTxGrantWaitActivated); + otLogDebgPlat(" txGrantWaitTimeout:%u", metrics.mNumTxGrantWaitTimeout); + otLogDebgPlat(" txGrantDeactivatedDuringRequest:%u", metrics.mNumTxGrantDeactivatedDuringRequest); + otLogDebgPlat(" txDelayedGrant:%u", metrics.mNumTxDelayedGrant); + otLogDebgPlat(" avgTxRequestToGrantTime:%u", metrics.mAvgTxRequestToGrantTime); + otLogDebgPlat(" rxRequest:%u", metrics.mNumRxRequest); + otLogDebgPlat(" rxGrantImmediate:%u", metrics.mNumRxGrantImmediate); + otLogDebgPlat(" rxGrantWait:%u", metrics.mNumRxGrantWait); + otLogDebgPlat(" rxGrantWaitActivated:%u", metrics.mNumRxGrantWaitActivated); + otLogDebgPlat(" rxGrantWaitTimeout:%u", metrics.mNumRxGrantWaitTimeout); + otLogDebgPlat(" rxGrantDeactivatedDuringRequest:%u", metrics.mNumRxGrantDeactivatedDuringRequest); + otLogDebgPlat(" rxDelayedGrant:%u", metrics.mNumRxDelayedGrant); + otLogDebgPlat(" avgRxRequestToGrantTime:%u", metrics.mAvgRxRequestToGrantTime); + otLogDebgPlat(" rxGrantNone:%u", metrics.mNumRxGrantNone); + otLogDebgPlat(" stopped:%u", metrics.mStopped); + + start = buf; + start += Snprintf(start, static_cast(end - start), " grantGlitch:%u", metrics.mNumGrantGlitch); + } + break; + + case SPINEL_PROP_MAC_SCAN_MASK: + { + constexpr uint8_t kNumChannels = 16; + uint8_t channels[kNumChannels]; + spinel_size_t size; + + unpacked = spinel_datatype_unpack(data, len, SPINEL_DATATYPE_DATA_S, channels, &size); + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), ", channels:"); + + for (uint8_t i = 0; i < size; i++) + { + start += Snprintf(start, static_cast(end - start), "%u ", channels[i]); + } + } + break; + + case SPINEL_PROP_RCP_ENH_ACK_PROBING: + { + uint16_t saddr; + uint8_t m8[OT_EXT_ADDRESS_SIZE]; + uint8_t flags; + + unpacked = spinel_datatype_unpack( + data, len, SPINEL_DATATYPE_UINT16_S SPINEL_DATATYPE_EUI64_S SPINEL_DATATYPE_UINT8_S, &saddr, m8, &flags); + + VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE); + start += Snprintf(start, static_cast(end - start), + ", saddr:%04x, extaddr:%02x%02x%02x%02x%02x%02x%02x%02x, flags:0x%02x", saddr, m8[0], m8[1], + m8[2], m8[3], m8[4], m8[5], m8[6], m8[7], flags); + } + break; + } + +exit: + if (error == OT_ERROR_NONE) + { + otLogDebgPlat("%s", buf); + } + else + { + otLogDebgPlat("%s, failed to parse spinel frame !", prefix); + } + + return; +} + } // namespace Spinel } // namespace ot diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c index 190381db5..3e580182a 100644 --- a/src/lib/spinel/spinel.c +++ b/src/lib/spinel/spinel.c @@ -1235,6 +1235,7 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) {SPINEL_PROP_PHY_PCAP_ENABLED, "PHY_PCAP_ENABLED"}, {SPINEL_PROP_PHY_CHAN_PREFERRED, "PHY_CHAN_PREFERRED"}, {SPINEL_PROP_PHY_CHAN_MAX_POWER, "PHY_CHAN_MAX_POWER"}, + {SPINEL_PROP_PHY_REGION_CODE, "PHY_REGION_CODE"}, {SPINEL_PROP_JAM_DETECT_ENABLE, "JAM_DETECT_ENABLE"}, {SPINEL_PROP_JAM_DETECTED, "JAM_DETECTED"}, {SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD, "JAM_DETECT_RSSI_THRESHOLD"}, @@ -1400,6 +1401,7 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) {SPINEL_PROP_CHILD_SUPERVISION_INTERVAL, "CHILD_SUPERVISION_INTERVAL"}, {SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT, "CHILD_SUPERVISION_CHECK_TIMEOUT"}, {SPINEL_PROP_RCP_VERSION, "RCP_VERSION"}, + {SPINEL_PROP_RCP_TIMESTAMP, "TIMESTAMP"}, {SPINEL_PROP_RCP_ENH_ACK_PROBING, "ENH_ACK_PROBING"}, {SPINEL_PROP_RCP_CSL_ACCURACY, "CSL_ACCURACY"}, {SPINEL_PROP_RCP_CSL_UNCERTAINTY, "CSL_UNCERTAINTY"}, diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index 845385756..17e16d1be 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -4831,6 +4831,9 @@ typedef uint32_t spinel_prop_key_t; // ---------------------------------------------------------------------------- #define SPINEL_HEADER_FLAG 0x80 +#define SPINEL_HEADER_FLAGS_SHIFT 6 +#define SPINEL_HEADER_FLAGS_MASK (3 << SPINEL_HEADER_FLAGS_SHIFT) +#define SPINEL_HEADER_GET_FLAG(x) (((x)&SPINEL_HEADER_FLAGS_MASK) >> SPINEL_HEADER_FLAGS_SHIFT) #define SPINEL_HEADER_TID_SHIFT 0 #define SPINEL_HEADER_TID_MASK (15 << SPINEL_HEADER_TID_SHIFT)