1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file contains definitions for the diagnostics module. 32 */ 33 34 #ifndef FACTORY_DIAGS_HPP_ 35 #define FACTORY_DIAGS_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #if OPENTHREAD_CONFIG_DIAG_ENABLE 40 41 #include <string.h> 42 43 #include <openthread/platform/radio.h> 44 45 #include "common/error.hpp" 46 #include "common/locator.hpp" 47 #include "common/non_copyable.hpp" 48 #include "common/string.hpp" 49 50 namespace ot { 51 namespace FactoryDiags { 52 53 class Diags : public InstanceLocator, private NonCopyable 54 { 55 public: 56 /** 57 * Constructor. 58 * 59 * @param[in] aInstance The OpenThread instance. 60 * 61 */ 62 explicit Diags(Instance &aInstance); 63 64 /** 65 * Processes a factory diagnostics command line. 66 * 67 * @param[in] aString A null-terminated input string. 68 * @param[out] aOutput The diagnostics execution result. 69 * @param[in] aOutputMaxLen The output buffer size. 70 * 71 */ 72 Error ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen); 73 74 /** 75 * Processes a factory diagnostics command line. 76 * 77 * @param[in] aArgsLength The number of args in @p aArgs. 78 * @param[in] aArgs The arguments of diagnostics command line. 79 * @param[out] aOutput The diagnostics execution result. 80 * @param[in] aOutputMaxLen The output buffer size. 81 * 82 * @retval kErrorInvalidArgs The command is supported but invalid arguments provided. 83 * @retval kErrorNone The command is successfully process. 84 * @retval kErrorNotImplemented The command is not supported. 85 * 86 */ 87 Error ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 88 89 /** 90 * Indicates whether or not the factory diagnostics mode is enabled. 91 * 92 * @retval TRUE if factory diagnostics mode is enabled 93 * @retval FALSE if factory diagnostics mode is disabled. 94 * 95 */ 96 bool IsEnabled(void); 97 98 /** 99 * The platform driver calls this method to notify OpenThread diagnostics module that the alarm has fired. 100 * 101 */ 102 void AlarmFired(void); 103 104 /** 105 * The radio driver calls this method to notify OpenThread diagnostics module of a received frame. 106 * 107 * @param[in] aFrame A pointer to the received frame or `nullptr` if the receive operation failed. 108 * @param[in] aError kErrorNone when successfully received a frame, 109 * kErrorAbort when reception was aborted and a frame was not received, 110 * kErrorNoBufs when a frame could not be received due to lack of rx buffer space. 111 * 112 */ 113 void ReceiveDone(otRadioFrame *aFrame, Error aError); 114 115 /** 116 * The radio driver calls this method to notify OpenThread diagnostics module that the transmission has completed. 117 * 118 * @param[in] aError kErrorNone when the frame was transmitted, 119 * kErrorChannelAccessFailure tx could not take place due to activity on channel, 120 * kErrorAbort when transmission was aborted for other reasons. 121 * 122 */ 123 void TransmitDone(Error aError); 124 125 private: 126 static constexpr uint8_t kMaxArgs = OPENTHREAD_CONFIG_DIAG_CMD_LINE_ARGS_MAX; 127 128 struct Command 129 { 130 const char *mName; 131 Error (Diags::*mCommand)(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 132 }; 133 134 struct Stats 135 { Clearot::FactoryDiags::Diags::Stats136 void Clear(void) { memset(this, 0, sizeof(*this)); } 137 138 uint32_t mReceivedPackets; 139 uint32_t mSentPackets; 140 int8_t mFirstRssi; 141 uint8_t mFirstLqi; 142 int8_t mLastRssi; 143 uint8_t mLastLqi; 144 }; 145 146 struct RawPowerSetting 147 { 148 static constexpr uint16_t kMaxDataSize = OPENTHREAD_CONFIG_POWER_CALIBRATION_RAW_POWER_SETTING_SIZE; 149 static constexpr uint16_t kInfoStringSize = kMaxDataSize * 2 + 1; 150 typedef String<kInfoStringSize> InfoString; 151 ToStringot::FactoryDiags::Diags::RawPowerSetting152 InfoString ToString(void) const 153 { 154 InfoString string; 155 156 string.AppendHexBytes(mData, mLength); 157 158 return string; 159 } 160 operator !=ot::FactoryDiags::Diags::RawPowerSetting161 bool operator!=(const RawPowerSetting &aOther) const 162 { 163 return (mLength != aOther.mLength) || (memcmp(mData, aOther.mData, mLength) != 0); 164 } 165 166 uint8_t mData[kMaxDataSize]; 167 uint16_t mLength; 168 }; 169 170 struct PowerSettings 171 { operator !=ot::FactoryDiags::Diags::PowerSettings172 bool operator!=(const PowerSettings &aOther) const 173 { 174 return (mTargetPower != aOther.mTargetPower) || (mActualPower != aOther.mActualPower) || 175 (mRawPowerSetting != aOther.mRawPowerSetting); 176 } 177 178 int16_t mTargetPower; 179 int16_t mActualPower; 180 RawPowerSetting mRawPowerSetting; 181 }; 182 183 Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]); 184 Error ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 185 Error ProcessContinuousWave(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 186 Error ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 187 Error ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 188 Error ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 189 Error ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 190 Error ProcessPowerSettings(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 191 Error ProcessRawPowerSetting(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 192 Error ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 193 Error ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 194 Error ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 195 Error ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 196 Error ProcessStream(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 197 #if OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI 198 Error ProcessEcho(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen); 199 #endif 200 201 Error GetRawPowerSetting(RawPowerSetting &aRawPowerSetting); 202 Error GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings); 203 204 void TransmitPacket(void); 205 206 static void AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen); 207 static Error ParseLong(char *aString, long &aLong); 208 static Error ParseBool(char *aString, bool &aBool); 209 210 static const struct Command sCommands[]; 211 212 #if OPENTHREAD_FTD || OPENTHREAD_MTD || (OPENTHREAD_RADIO && OPENTHREAD_RADIO_CLI) 213 Stats mStats; 214 215 otRadioFrame *mTxPacket; 216 uint32_t mTxPeriod; 217 uint32_t mTxPackets; 218 uint8_t mChannel; 219 int8_t mTxPower; 220 uint8_t mTxLen; 221 bool mRepeatActive; 222 bool mDiagSendOn; 223 #endif 224 }; 225 226 } // namespace FactoryDiags 227 } // namespace ot 228 229 #endif // #if OPENTHREAD_CONFIG_DIAG_ENABLE 230 231 #endif // FACTORY_DIAGS_HPP_ 232