[diag] add gpio diag command support (#8316)

diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c
index 4d6ab88..9f9db6e 100644
--- a/examples/platforms/simulation/radio.c
+++ b/examples/platforms/simulation/radio.c
@@ -166,6 +166,13 @@
 static otMacKeyMaterial sNextKey;
 static otRadioKeyType   sKeyType;
 
+enum
+{
+    SIM_GPIO = 0,
+};
+
+static bool sGpioValue = false;
+
 static int8_t GetRssi(uint16_t aChannel);
 
 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
@@ -1399,3 +1406,25 @@
         }
     }
 }
+
+otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue)
+{
+    otError error = OT_ERROR_NONE;
+
+    otEXPECT_ACTION(aGpio == SIM_GPIO, error = OT_ERROR_INVALID_ARGS);
+    sGpioValue = aValue;
+
+exit:
+    return error;
+}
+
+otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue)
+{
+    otError error = OT_ERROR_NONE;
+
+    otEXPECT_ACTION((aGpio == SIM_GPIO) && (aValue != NULL), error = OT_ERROR_INVALID_ARGS);
+    *aValue = sGpioValue;
+
+exit:
+    return error;
+}
diff --git a/include/openthread/diag.h b/include/openthread/diag.h
index 96571f9..3b1f80a 100644
--- a/include/openthread/diag.h
+++ b/include/openthread/diag.h
@@ -85,8 +85,13 @@
  * @param[out]  aOutput         The diagnostics execution result.
  * @param[in]   aOutputMaxLen   The output buffer size.
  *
+ * @retval  OT_ERROR_NONE               The command is successfully process.
+ * @retval  OT_ERROR_INVALID_ARGS       The command is supported but invalid arguments provided.
+ * @retval  OT_ERROR_NOT_IMPLEMENTED    The command is not supported.
+ * @retval  OT_ERROR_NO_BUFS            The command string is too long.
+ *
  */
-void otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen);
+otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen);
 
 /**
  * This function indicates whether or not the factory diagnostics mode is enabled.
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index 4e96a9c..a361239 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -53,7 +53,7 @@
  * @note This number versions both OpenThread platform and user APIs.
  *
  */
-#define OPENTHREAD_API_VERSION (256)
+#define OPENTHREAD_API_VERSION (257)
 
 /**
  * @addtogroup api-instance
diff --git a/include/openthread/platform/diag.h b/include/openthread/platform/diag.h
index 9dee346..46e9444 100644
--- a/include/openthread/platform/diag.h
+++ b/include/openthread/platform/diag.h
@@ -130,6 +130,32 @@
 void otPlatDiagAlarmCallback(otInstance *aInstance);
 
 /**
+ * This function sets the gpio value.
+ *
+ * @param[in]  aGpio   The gpio number.
+ * @param[in]  aValue  true to set the gpio to high level, or false otherwise.
+ *
+ * @retval OT_ERROR_NONE             Successfully set the gpio.
+ * @retval OT_ERROR_INVALID_ARGS     @p aGpio is not supported.
+ * @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on the platform.
+ *
+ */
+otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue);
+
+/**
+ * This function gets the gpio value.
+ *
+ * @param[in]   aGpio   The gpio number.
+ * @param[out]  aValue  A pointer where to put gpio value.
+ *
+ * @retval OT_ERROR_NONE             Successfully got the gpio value.
+ * @retval OT_ERROR_INVALID_ARGS     @p aGpio is not supported or @p aValue is NULL.
+ * @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on the platform.
+ *
+ */
+otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue);
+
+/**
  * @}
  *
  */
diff --git a/src/core/api/diags_api.cpp b/src/core/api/diags_api.cpp
index 7883e12..eb83bef 100644
--- a/src/core/api/diags_api.cpp
+++ b/src/core/api/diags_api.cpp
@@ -42,11 +42,11 @@
 
 using namespace ot;
 
-void otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
+otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
 {
     AssertPointerIsNotNull(aString);
 
-    AsCoreType(aInstance).Get<FactoryDiags::Diags>().ProcessLine(aString, aOutput, aOutputMaxLen);
+    return AsCoreType(aInstance).Get<FactoryDiags::Diags>().ProcessLine(aString, aOutput, aOutputMaxLen);
 }
 
 otError otDiagProcessCmd(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
diff --git a/src/core/diags/README.md b/src/core/diags/README.md
index 090aa03..7fa128f 100644
--- a/src/core/diags/README.md
+++ b/src/core/diags/README.md
@@ -14,6 +14,7 @@
 - [diag repeat](#diag-repeat-delay-length)
 - [diag radio](#diag-radio-sleep)
 - [diag stats](#diag-stats)
+- [diag gpio](#diag-gpio-get-gpio)
 - [diag stop](#diag-stop)
 
 ### diag
@@ -157,6 +158,27 @@
 stats cleared
 ```
 
+### diag gpio get \<gpio\>
+
+Get the gpio value.
+
+```bash
+> diag gpio get 0
+1
+Done
+```
+
+### diag gpio set \<gpio\> \<value\>
+
+Set the gpio value.
+
+The parameter `value` has to be `0` or `1`.
+
+```bash
+> diag gpio set 0 1
+Done
+```
+
 ### diag stop
 
 Stop diagnostics mode and print statistics.
diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp
index 6410421..ec9a0c7 100644
--- a/src/core/diags/factory_diags.cpp
+++ b/src/core/diags/factory_diags.cpp
@@ -70,8 +70,8 @@
 #if OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI
 
 const struct Diags::Command Diags::sCommands[] = {
-    {"channel", &Diags::ProcessChannel}, {"echo", &Diags::ProcessEcho}, {"power", &Diags::ProcessPower},
-    {"start", &Diags::ProcessStart},     {"stop", &Diags::ProcessStop},
+    {"channel", &Diags::ProcessChannel}, {"echo", &Diags::ProcessEcho},   {"gpio", &Diags::ProcessGpio},
+    {"power", &Diags::ProcessPower},     {"start", &Diags::ProcessStart}, {"stop", &Diags::ProcessStop},
 };
 
 Diags::Diags(Instance &aInstance)
@@ -181,9 +181,9 @@
 #else // OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI
 // For OPENTHREAD_FTD, OPENTHREAD_MTD, OPENTHREAD_RADIO_CLI
 const struct Diags::Command Diags::sCommands[] = {
-    {"channel", &Diags::ProcessChannel}, {"power", &Diags::ProcessPower}, {"radio", &Diags::ProcessRadio},
-    {"repeat", &Diags::ProcessRepeat},   {"send", &Diags::ProcessSend},   {"start", &Diags::ProcessStart},
-    {"stats", &Diags::ProcessStats},     {"stop", &Diags::ProcessStop},
+    {"channel", &Diags::ProcessChannel}, {"gpio", &Diags::ProcessGpio},     {"power", &Diags::ProcessPower},
+    {"radio", &Diags::ProcessRadio},     {"repeat", &Diags::ProcessRepeat}, {"send", &Diags::ProcessSend},
+    {"start", &Diags::ProcessStart},     {"stats", &Diags::ProcessStats},   {"stop", &Diags::ProcessStop},
 };
 
 Diags::Diags(Instance &aInstance)
@@ -543,6 +543,37 @@
 
 #endif // OPENTHREAD_RADIO
 
+Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+{
+    Error    error = kErrorNone;
+    long     value;
+    uint32_t gpio;
+    bool     level;
+
+    if ((aArgsLength == 2) && (strcmp(aArgs[0], "get") == 0))
+    {
+        SuccessOrExit(error = ParseLong(aArgs[1], value));
+        gpio = static_cast<uint32_t>(value);
+        SuccessOrExit(error = otPlatDiagGpioGet(gpio, &level));
+        snprintf(aOutput, aOutputMaxLen, "%d\r\n", level);
+    }
+    else if ((aArgsLength == 3) && (strcmp(aArgs[0], "set") == 0))
+    {
+        SuccessOrExit(error = ParseLong(aArgs[1], value));
+        gpio = static_cast<uint32_t>(value);
+        SuccessOrExit(error = ParseBool(aArgs[2], level));
+        SuccessOrExit(error = otPlatDiagGpioSet(gpio, level));
+    }
+    else
+    {
+        error = kErrorInvalidArgs;
+    }
+
+exit:
+    AppendErrorResult(error, aOutput, aOutputMaxLen);
+    return error;
+}
+
 void Diags::AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen)
 {
     if (aError != kErrorNone)
@@ -558,6 +589,19 @@
     return (*endptr == '\0') ? kErrorNone : kErrorParse;
 }
 
+Error Diags::ParseBool(char *aString, bool &aBool)
+{
+    Error error;
+    long  value;
+
+    SuccessOrExit(error = ParseLong(aString, value));
+    VerifyOrExit((value == 0) || (value == 1), error = kErrorParse);
+    aBool = static_cast<bool>(value);
+
+exit:
+    return error;
+}
+
 Error Diags::ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[])
 {
     Error                     error;
@@ -571,7 +615,7 @@
     return error;
 }
 
-void Diags::ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
 {
     constexpr uint16_t kMaxCommandBuffer = OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE;
 
@@ -591,7 +635,7 @@
     {
     case kErrorNone:
         aOutput[0] = '\0'; // In case there is no output.
-        IgnoreError(ProcessCmd(argCount, &args[0], aOutput, aOutputMaxLen));
+        error      = ProcessCmd(argCount, &args[0], aOutput, aOutputMaxLen);
         break;
 
     case kErrorNoBufs:
@@ -606,6 +650,8 @@
         snprintf(aOutput, aOutputMaxLen, "failed to parse command string\r\n");
         break;
     }
+
+    return error;
 }
 
 Error Diags::ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
@@ -663,4 +709,20 @@
 } // namespace FactoryDiags
 } // namespace ot
 
+OT_TOOL_WEAK otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue)
+{
+    OT_UNUSED_VARIABLE(aGpio);
+    OT_UNUSED_VARIABLE(aValue);
+
+    return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+OT_TOOL_WEAK otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue)
+{
+    OT_UNUSED_VARIABLE(aGpio);
+    OT_UNUSED_VARIABLE(aValue);
+
+    return OT_ERROR_NOT_IMPLEMENTED;
+}
+
 #endif // OPENTHREAD_CONFIG_DIAG_ENABLE
diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp
index 26ccd9e..e3c7c2a 100644
--- a/src/core/diags/factory_diags.hpp
+++ b/src/core/diags/factory_diags.hpp
@@ -68,7 +68,7 @@
      * @param[in]   aOutputMaxLen  The output buffer size.
      *
      */
-    void ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen);
+    Error ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen);
 
     /**
      * This method processes a factory diagnostics command line.
@@ -144,6 +144,7 @@
 
     Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]);
     Error ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+    Error ProcessGpio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
     Error ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
     Error ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
     Error ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
@@ -159,6 +160,7 @@
 
     static void  AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen);
     static Error ParseLong(char *aString, long &aLong);
+    static Error ParseBool(char *aString, bool &aBool);
 
     static const struct Command sCommands[];
 
diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp
index c9eda5c..21bc329 100644
--- a/src/lib/spinel/radio_spinel_impl.hpp
+++ b/src/lib/spinel/radio_spinel_impl.hpp
@@ -790,6 +790,7 @@
     {
         spinel_ssize_t unpacked;
 
+        mError = OT_ERROR_NONE;
         VerifyOrExit(mDiagOutput != nullptr);
         unpacked =
             spinel_datatype_unpack_in_place(aBuffer, aLength, SPINEL_DATATYPE_UTF8_S, mDiagOutput, &mDiagOutputMaxLen);
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index aa04bc5..83df7c2 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -1370,7 +1370,7 @@
     }
 #endif
 
-    otDiagProcessCmdLine(mInstance, string, output, sizeof(output));
+    SuccessOrExit(error = otDiagProcessCmdLine(mInstance, string, output, sizeof(output)));
 
     // Prepare the response
     SuccessOrExit(error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_NEST_STREAM_MFG));
diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp
index 8fb63bf..495cc69 100644
--- a/src/posix/platform/radio.cpp
+++ b/src/posix/platform/radio.cpp
@@ -547,6 +547,34 @@
     return;
 }
 
+otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue)
+{
+    otError error;
+    char    cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
+
+    snprintf(cmd, sizeof(cmd), "gpio set %d %d", aGpio, aValue);
+    SuccessOrExit(error = sRadioSpinel.PlatDiagProcess(cmd, nullptr, 0));
+
+exit:
+    return error;
+}
+
+otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue)
+{
+    otError error;
+    char    cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
+    char    output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
+    char *  str;
+
+    snprintf(cmd, sizeof(cmd), "gpio get %d", aGpio);
+    SuccessOrExit(error = sRadioSpinel.PlatDiagProcess(cmd, output, sizeof(output)));
+    VerifyOrExit((str = strtok(output, "\r")) != nullptr, error = OT_ERROR_FAILED);
+    *aValue = static_cast<bool>(atoi(str));
+
+exit:
+    return error;
+}
+
 void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
 {
     OT_UNUSED_VARIABLE(aInstance);
diff --git a/tests/fuzz/fuzzer_platform.cpp b/tests/fuzz/fuzzer_platform.cpp
index e93cbfc..1c00d5e 100644
--- a/tests/fuzz/fuzzer_platform.cpp
+++ b/tests/fuzz/fuzzer_platform.cpp
@@ -207,12 +207,14 @@
     return OT_ERROR_NOT_IMPLEMENTED;
 }
 
-void otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
+otError otDiagProcessCmdLine(otInstance *aInstance, const char *aString, char *aOutput, size_t aOutputMaxLen)
 {
     OT_UNUSED_VARIABLE(aInstance);
     OT_UNUSED_VARIABLE(aString);
     OT_UNUSED_VARIABLE(aOutput);
     OT_UNUSED_VARIABLE(aOutputMaxLen);
+
+    return OT_ERROR_NOT_IMPLEMENTED;
 }
 
 void otPlatReset(otInstance *aInstance)
diff --git a/tests/scripts/expect/cli-diags.exp b/tests/scripts/expect/cli-diags.exp
new file mode 100755
index 0000000..6866808
--- /dev/null
+++ b/tests/scripts/expect/cli-diags.exp
@@ -0,0 +1,175 @@
+#!/usr/bin/expect -f
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are met:
+#  1. Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#  2. Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#  3. Neither the name of the copyright holder nor the
+#     names of its contributors may be used to endorse or promote products
+#     derived from this software without specific prior written permission.
+#
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+#  POSSIBILITY OF SUCH DAMAGE.
+#
+
+source "tests/scripts/expect/_common.exp"
+source "tests/scripts/expect/_multinode.exp"
+
+spawn_node 1
+spawn_node 2
+
+switch_node 1
+send "diag start\n"
+expect "start diagnostics mode"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag channel 11\n"
+expect "set channel to 11"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag stats clear\n"
+expect "stats cleared"
+expect_line "Done"
+
+switch_node 2
+
+send "diag start\n"
+expect "start diagnostics mode"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag channel 11\n"
+expect "set channel to 11"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag stats clear\n"
+expect "stats cleared"
+expect_line "Done"
+
+send "diag send 10 100\n"
+expect "sending 0xa packet(s), length 0x64"
+expect "status 0x00"
+expect_line "Done"
+
+sleep 2
+
+send "diag stats\n"
+expect "received packets: 0"
+expect "sent packets: 10"
+expect "first received packet: rssi=0, lqi=0"
+expect "last received packet: rssi=0, lqi=0"
+expect_line "Done"
+
+switch_node 1
+
+send "diag stats\n"
+expect "received packets: 10"
+expect "sent packets: 0"
+expect "first received packet: rssi=-20, lqi=0"
+expect "last received packet: rssi=-20, lqi=0"
+expect_line "Done"
+
+send "diag stats clear\n"
+expect "stats cleared"
+expect_line "Done"
+
+switch_node 2
+
+send "diag repeat 20 100\n"
+expect "sending packets of length 0x64 at the delay of 0x14 ms"
+expect "status 0x00"
+expect_line "Done"
+sleep 1
+send "diag repeat stop\n"
+expect "repeated packet transmission is stopped"
+expect "status 0x00"
+expect_line "Done"
+
+switch_node 1
+
+send "diag stats\n"
+expect -r {received packets: \d+}
+expect "sent packets: 0"
+expect "first received packet: rssi=-20, lqi=0"
+expect "last received packet: rssi=-20, lqi=0"
+expect_line "Done"
+
+send "diag stats clear\n"
+expect "stats cleared"
+expect_line "Done"
+
+dispose_all
+
+
+spawn_node 1
+
+send "diag start\n"
+expect "start diagnostics mode"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag channel 11\n"
+expect "set channel to 11"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag power 10\n"
+expect "set tx power to 10 dBm"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag radio sleep\n"
+expect "set radio from receive to sleep"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag radio state\n"
+expect "sleep"
+expect_line "Done"
+
+send "diag radio receive\n"
+expect "set radio from sleep to receive on channel 11"
+expect "status 0x00"
+expect_line "Done"
+
+send "diag radio state\n"
+expect "receive"
+expect_line "Done"
+
+send "diag gpio set 0 1\n"
+expect_line "Done"
+
+send "diag gpio get 0\n"
+expect "1"
+expect_line "Done"
+
+send "diag invalid_commad\n"
+expect "Error 35: InvalidCommand"
+
+send "diag stop\n"
+expect_line "Done"
+
+send "diag channel\n"
+expect "failed"
+expect "status 0xd"
+expect "Error 13: InvalidState"
+
+dispose_all
diff --git a/tests/scripts/expect/posix-diag-rcp.exp b/tests/scripts/expect/posix-diag-rcp.exp
index 08b9553..e585d60 100755
--- a/tests/scripts/expect/posix-diag-rcp.exp
+++ b/tests/scripts/expect/posix-diag-rcp.exp
@@ -42,21 +42,15 @@
 expect "diagnostics mode is enabled"
 expect_line "Done"
 send "diag rcp channel\n"
-expect "failed"
-expect "status 0x7"
-expect_line "Done"
+expect "Error 7: InvalidArgs"
 send "diag rcp channel 11\n"
 expect_line "Done"
 send "diag rcp power\n"
-expect "failed"
-expect "status 0x7"
-expect_line "Done"
+expect "Error 7: InvalidArgs"
 send "diag rcp power 10\n"
 expect_line "Done"
 send "diag rcp echo\n"
-expect "failed"
-expect "status 0x7"
-expect_line "Done"
+expect "Error 7: InvalidArgs"
 send "diag rcp echo 0123456789\n"
 expect_line "0123456789"
 expect_line "Done"