1 /*
2  *  Copyright (c) 2024, 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 RCP capability diagnostics module.
32  */
33 
34 #ifndef OT_POSIX_PLATFORM_RCP_CAPS_DIAG_HPP_
35 #define OT_POSIX_PLATFORM_RCP_CAPS_DIAG_HPP_
36 
37 #include "platform-posix.h"
38 
39 #if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
40 #include <openthread/platform/diag.h>
41 
42 #include "lib/spinel/radio_spinel.hpp"
43 #include "lib/spinel/spinel.h"
44 
45 #if !OPENTHREAD_CONFIG_DIAG_ENABLE
46 #error "OPENTHREAD_CONFIG_DIAG_ENABLE is required for OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE"
47 #endif
48 
49 namespace ot {
50 namespace Posix {
51 
52 class RcpCapsDiag
53 {
54 public:
55     /**
56      * Constructor initializes the object.
57      *
58      * @param[in]  aRadioSpinel  A reference to the Spinel::RadioSpinel instance.
59      *
60      */
RcpCapsDiag(Spinel::RadioSpinel & aRadioSpinel)61     explicit RcpCapsDiag(Spinel::RadioSpinel &aRadioSpinel)
62         : mRadioSpinel(aRadioSpinel)
63         , mOutputCallback(nullptr)
64         , mOutputContext(nullptr)
65         , mDiagOutput(nullptr)
66         , mDiagOutputLength(0)
67     {
68     }
69 
70     /**
71      * Processes RCP capability diagnostics commands.
72      *
73      * @param[in]   aArgs           The arguments of diagnostics command line.
74      * @param[in]   aArgsLength     The number of arguments in @p aArgs.
75      *
76      * @retval  OT_ERROR_INVALID_ARGS       The command is supported but invalid arguments provided.
77      * @retval  OT_ERROR_NONE               The command is successfully processed.
78      * @retval  OT_ERROR_INVALID_COMMAND    The command is not valid or not supported.
79      *
80      */
81     otError DiagProcess(char *aArgs[], uint8_t aArgsLength);
82 
83     /**
84      * Sets the diag output callback.
85      *
86      * @param[in]  aCallback   A pointer to a function that is called on outputting diag messages.
87      * @param[in]  aContext    A user context pointer.
88      *
89      */
90     void SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void *aContext);
91 
92 private:
93     template <uint32_t aCommand, spinel_prop_key_t aKey> otError HandleSpinelCommand(void);
94     typedef otError (RcpCapsDiag::*SpinelCommandHandler)(void);
95 
96     enum Category : uint8_t
97     {
98         kCategoryBasic,
99         kCategoryThread1_1,
100         kCategoryThread1_2,
101         kCategoryUtils,
102         kNumCategories,
103     };
104 
105     struct SpinelEntry
106     {
107         Category                          mCategory;
108         uint32_t                          mCommand;
109         spinel_prop_key_t                 mKey;
110         RcpCapsDiag::SpinelCommandHandler mHandler;
111     };
112 
113     static constexpr uint16_t kMaxNumChildren = 512;
114 
115     void ProcessSpinel(void);
116     void ProcessSpinelSpeed(void);
117     void ProcessCapabilityFlags(void);
118     void ProcessSrcMatchTable(void);
119     void TestSpinelCommands(Category aCategory);
120     void TestRadioCapbilityFlags(void);
121     void OutputRadioCapFlags(Category aCategory, uint32_t aRadioCaps, const uint32_t *aFlags, uint16_t aNumbFlags);
122     void TestSpinelCapbilityFlags(void);
123     void OutputSpinelCapFlags(Category        aCategory,
124                               const uint8_t  *aCapsData,
125                               spinel_size_t   aCapsLength,
126                               const uint32_t *aFlags,
127                               uint16_t        aNumbFlags);
128     bool IsSpinelCapabilitySupported(const uint8_t *aCapsData, spinel_size_t aCapsLength, uint32_t aCapability);
129     void OutputExtendedSrcMatchTableSize(void);
130     void OutputShortSrcMatchTableSize(void);
131 
132     static void HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext);
133     void        HandleDiagOutput(const char *aFormat, va_list aArguments);
134 
135     void OutputFormat(const char *aName, const char *aValue);
136     void OutputFormat(const char *aName, uint32_t aValue);
137     void OutputResult(const SpinelEntry &aEntry, otError error);
138     void Output(const char *aFormat, ...);
139 
140     static const char *SupportToString(bool aSupport);
141     static const char *RadioCapbilityToString(uint32_t aCapability);
142     static const char *CategoryToString(Category aCategory);
143 
144     static const struct SpinelEntry sSpinelEntries[];
145 
146     Spinel::RadioSpinel     &mRadioSpinel;
147     otPlatDiagOutputCallback mOutputCallback;
148     void                    *mOutputContext;
149     char                    *mDiagOutput;
150     uint16_t                 mDiagOutputLength;
151 };
152 
153 } // namespace Posix
154 } // namespace ot
155 #endif // OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
156 #endif // OT_POSIX_PLATFORM_RCP_CAPS_DIAG_HPP_
157