xref: /aosp_15_r20/external/openthread/src/cli/cli_commissioner.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2019, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker /**
30*cfb92d14SAndroid Build Coastguard Worker  * @file
31*cfb92d14SAndroid Build Coastguard Worker  *   This file implements a simple CLI for the Commissioner role.
32*cfb92d14SAndroid Build Coastguard Worker  */
33*cfb92d14SAndroid Build Coastguard Worker 
34*cfb92d14SAndroid Build Coastguard Worker #include "cli_commissioner.hpp"
35*cfb92d14SAndroid Build Coastguard Worker 
36*cfb92d14SAndroid Build Coastguard Worker #include "cli/cli.hpp"
37*cfb92d14SAndroid Build Coastguard Worker 
38*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
39*cfb92d14SAndroid Build Coastguard Worker 
40*cfb92d14SAndroid Build Coastguard Worker namespace ot {
41*cfb92d14SAndroid Build Coastguard Worker namespace Cli {
42*cfb92d14SAndroid Build Coastguard Worker 
43*cfb92d14SAndroid Build Coastguard Worker /**
44*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner announce
45*cfb92d14SAndroid Build Coastguard Worker  * @code
46*cfb92d14SAndroid Build Coastguard Worker  * commissioner announce 0x00050000 2 32 fdde:ad00:beef:0:0:ff:fe00:c00
47*cfb92d14SAndroid Build Coastguard Worker  * Done
48*cfb92d14SAndroid Build Coastguard Worker  * @endcode
49*cfb92d14SAndroid Build Coastguard Worker  * @cparam commissioner announce @ca{mask} @ca{count} @ca{period} @ca{destination}
50*cfb92d14SAndroid Build Coastguard Worker  *   * `mask`: Bitmask that identifies channels for sending MLE `Announce` messages.
51*cfb92d14SAndroid Build Coastguard Worker  *   * `count`: Number of MLE `Announce` transmissions per channel.
52*cfb92d14SAndroid Build Coastguard Worker  *   * `period`: Number of milliseconds between successive MLE `Announce` transmissions.
53*cfb92d14SAndroid Build Coastguard Worker  *   * `destination`: Destination IPv6 address for the message. The message may be multicast.
54*cfb92d14SAndroid Build Coastguard Worker  * @par
55*cfb92d14SAndroid Build Coastguard Worker  * Sends an Announce Begin message.
56*cfb92d14SAndroid Build Coastguard Worker  * @note Use this command only after successfully starting the %Commissioner role
57*cfb92d14SAndroid Build Coastguard Worker  * with the `commissioner start` command.
58*cfb92d14SAndroid Build Coastguard Worker  * @csa{commissioner start}
59*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerAnnounceBegin
60*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])61*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("announce")>(Arg aArgs[])
62*cfb92d14SAndroid Build Coastguard Worker {
63*cfb92d14SAndroid Build Coastguard Worker     otError      error;
64*cfb92d14SAndroid Build Coastguard Worker     uint32_t     mask;
65*cfb92d14SAndroid Build Coastguard Worker     uint8_t      count;
66*cfb92d14SAndroid Build Coastguard Worker     uint16_t     period;
67*cfb92d14SAndroid Build Coastguard Worker     otIp6Address address;
68*cfb92d14SAndroid Build Coastguard Worker 
69*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[0].ParseAsUint32(mask));
70*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[1].ParseAsUint8(count));
71*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[2].ParseAsUint16(period));
72*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[3].ParseAsIp6Address(address));
73*cfb92d14SAndroid Build Coastguard Worker 
74*cfb92d14SAndroid Build Coastguard Worker     error = otCommissionerAnnounceBegin(GetInstancePtr(), mask, count, period, &address);
75*cfb92d14SAndroid Build Coastguard Worker 
76*cfb92d14SAndroid Build Coastguard Worker exit:
77*cfb92d14SAndroid Build Coastguard Worker     return error;
78*cfb92d14SAndroid Build Coastguard Worker }
79*cfb92d14SAndroid Build Coastguard Worker 
80*cfb92d14SAndroid Build Coastguard Worker /**
81*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner energy
82*cfb92d14SAndroid Build Coastguard Worker  * @code
83*cfb92d14SAndroid Build Coastguard Worker  * commissioner energy 0x00050000 2 32 1000 fdde:ad00:beef:0:0:ff:fe00:c00
84*cfb92d14SAndroid Build Coastguard Worker  * Done
85*cfb92d14SAndroid Build Coastguard Worker  * Energy: 00050000 0 0 0 0
86*cfb92d14SAndroid Build Coastguard Worker  * @endcode
87*cfb92d14SAndroid Build Coastguard Worker  * @cparam commissioner energy @ca{mask} @ca{count} @ca{period} @ca{scanDuration} @ca{destination}
88*cfb92d14SAndroid Build Coastguard Worker  *   * `mask`: Bitmask that identifies channels for performing IEEE 802.15.4 energy scans.
89*cfb92d14SAndroid Build Coastguard Worker  *   * `count`: Number of IEEE 802.15.4 energy scans per channel.
90*cfb92d14SAndroid Build Coastguard Worker  *   * `period`: Number of milliseconds between successive IEEE 802.15.4 energy scans.
91*cfb92d14SAndroid Build Coastguard Worker  *   * `scanDuration`: Scan duration in milliseconds to use when
92*cfb92d14SAndroid Build Coastguard Worker  *     performing an IEEE 802.15.4 energy scan.
93*cfb92d14SAndroid Build Coastguard Worker  *   * `destination`: Destination IPv6 address for the message. The message may be multicast.
94*cfb92d14SAndroid Build Coastguard Worker  * @par
95*cfb92d14SAndroid Build Coastguard Worker  * Sends an Energy Scan Query message. Command output is printed as it is received.
96*cfb92d14SAndroid Build Coastguard Worker  * @note Use this command only after successfully starting the %Commissioner role
97*cfb92d14SAndroid Build Coastguard Worker  * with the `commissioner start` command.
98*cfb92d14SAndroid Build Coastguard Worker  * @csa{commissioner start}
99*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerEnergyScan
100*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])101*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("energy")>(Arg aArgs[])
102*cfb92d14SAndroid Build Coastguard Worker {
103*cfb92d14SAndroid Build Coastguard Worker     otError      error;
104*cfb92d14SAndroid Build Coastguard Worker     uint32_t     mask;
105*cfb92d14SAndroid Build Coastguard Worker     uint8_t      count;
106*cfb92d14SAndroid Build Coastguard Worker     uint16_t     period;
107*cfb92d14SAndroid Build Coastguard Worker     uint16_t     scanDuration;
108*cfb92d14SAndroid Build Coastguard Worker     otIp6Address address;
109*cfb92d14SAndroid Build Coastguard Worker 
110*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[0].ParseAsUint32(mask));
111*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[1].ParseAsUint8(count));
112*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[2].ParseAsUint16(period));
113*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[3].ParseAsUint16(scanDuration));
114*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[4].ParseAsIp6Address(address));
115*cfb92d14SAndroid Build Coastguard Worker 
116*cfb92d14SAndroid Build Coastguard Worker     error = otCommissionerEnergyScan(GetInstancePtr(), mask, count, period, scanDuration, &address,
117*cfb92d14SAndroid Build Coastguard Worker                                      &Commissioner::HandleEnergyReport, this);
118*cfb92d14SAndroid Build Coastguard Worker 
119*cfb92d14SAndroid Build Coastguard Worker exit:
120*cfb92d14SAndroid Build Coastguard Worker     return error;
121*cfb92d14SAndroid Build Coastguard Worker }
122*cfb92d14SAndroid Build Coastguard Worker 
Process(Arg aArgs[])123*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("joiner")>(Arg aArgs[])
124*cfb92d14SAndroid Build Coastguard Worker {
125*cfb92d14SAndroid Build Coastguard Worker     otError             error = OT_ERROR_NONE;
126*cfb92d14SAndroid Build Coastguard Worker     otExtAddress        addr;
127*cfb92d14SAndroid Build Coastguard Worker     const otExtAddress *addrPtr = nullptr;
128*cfb92d14SAndroid Build Coastguard Worker     otJoinerDiscerner   discerner;
129*cfb92d14SAndroid Build Coastguard Worker 
130*cfb92d14SAndroid Build Coastguard Worker     /**
131*cfb92d14SAndroid Build Coastguard Worker      * @cli commissioner joiner table
132*cfb92d14SAndroid Build Coastguard Worker      * @code
133*cfb92d14SAndroid Build Coastguard Worker      * commissioner joiner table
134*cfb92d14SAndroid Build Coastguard Worker      * | ID                    | PSKd                             | Expiration |
135*cfb92d14SAndroid Build Coastguard Worker      * +-----------------------+----------------------------------+------------+
136*cfb92d14SAndroid Build Coastguard Worker      * |                     * |                           J01NME |      81015 |
137*cfb92d14SAndroid Build Coastguard Worker      * |      d45e64fa83f81cf7 |                           J01NME |     101204 |
138*cfb92d14SAndroid Build Coastguard Worker      * | 0x0000000000000abc/12 |                           J01NME |     114360 |
139*cfb92d14SAndroid Build Coastguard Worker      * Done
140*cfb92d14SAndroid Build Coastguard Worker      * @endcode
141*cfb92d14SAndroid Build Coastguard Worker      * @par
142*cfb92d14SAndroid Build Coastguard Worker      * Lists all %Joiner entries in table format.
143*cfb92d14SAndroid Build Coastguard Worker      */
144*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0] == "table")
145*cfb92d14SAndroid Build Coastguard Worker     {
146*cfb92d14SAndroid Build Coastguard Worker         uint16_t     iter = 0;
147*cfb92d14SAndroid Build Coastguard Worker         otJoinerInfo joinerInfo;
148*cfb92d14SAndroid Build Coastguard Worker 
149*cfb92d14SAndroid Build Coastguard Worker         static const char *const kJoinerTableTitles[] = {"ID", "PSKd", "Expiration"};
150*cfb92d14SAndroid Build Coastguard Worker 
151*cfb92d14SAndroid Build Coastguard Worker         static const uint8_t kJoinerTableColumnWidths[] = {
152*cfb92d14SAndroid Build Coastguard Worker             23,
153*cfb92d14SAndroid Build Coastguard Worker             34,
154*cfb92d14SAndroid Build Coastguard Worker             12,
155*cfb92d14SAndroid Build Coastguard Worker         };
156*cfb92d14SAndroid Build Coastguard Worker 
157*cfb92d14SAndroid Build Coastguard Worker         OutputTableHeader(kJoinerTableTitles, kJoinerTableColumnWidths);
158*cfb92d14SAndroid Build Coastguard Worker 
159*cfb92d14SAndroid Build Coastguard Worker         while (otCommissionerGetNextJoinerInfo(GetInstancePtr(), &iter, &joinerInfo) == OT_ERROR_NONE)
160*cfb92d14SAndroid Build Coastguard Worker         {
161*cfb92d14SAndroid Build Coastguard Worker             switch (joinerInfo.mType)
162*cfb92d14SAndroid Build Coastguard Worker             {
163*cfb92d14SAndroid Build Coastguard Worker             case OT_JOINER_INFO_TYPE_ANY:
164*cfb92d14SAndroid Build Coastguard Worker                 OutputFormat("| %21s", "*");
165*cfb92d14SAndroid Build Coastguard Worker                 break;
166*cfb92d14SAndroid Build Coastguard Worker 
167*cfb92d14SAndroid Build Coastguard Worker             case OT_JOINER_INFO_TYPE_EUI64:
168*cfb92d14SAndroid Build Coastguard Worker                 OutputFormat("|      ");
169*cfb92d14SAndroid Build Coastguard Worker                 OutputExtAddress(joinerInfo.mSharedId.mEui64);
170*cfb92d14SAndroid Build Coastguard Worker                 break;
171*cfb92d14SAndroid Build Coastguard Worker 
172*cfb92d14SAndroid Build Coastguard Worker             case OT_JOINER_INFO_TYPE_DISCERNER:
173*cfb92d14SAndroid Build Coastguard Worker                 OutputFormat("| 0x%08lx%08lx/%2u",
174*cfb92d14SAndroid Build Coastguard Worker                              static_cast<unsigned long>(joinerInfo.mSharedId.mDiscerner.mValue >> 32),
175*cfb92d14SAndroid Build Coastguard Worker                              static_cast<unsigned long>(joinerInfo.mSharedId.mDiscerner.mValue & 0xffffffff),
176*cfb92d14SAndroid Build Coastguard Worker                              joinerInfo.mSharedId.mDiscerner.mLength);
177*cfb92d14SAndroid Build Coastguard Worker                 break;
178*cfb92d14SAndroid Build Coastguard Worker             }
179*cfb92d14SAndroid Build Coastguard Worker 
180*cfb92d14SAndroid Build Coastguard Worker             OutputFormat(" | %32s | %10lu |", joinerInfo.mPskd.m8, ToUlong(joinerInfo.mExpirationTime));
181*cfb92d14SAndroid Build Coastguard Worker             OutputNewLine();
182*cfb92d14SAndroid Build Coastguard Worker         }
183*cfb92d14SAndroid Build Coastguard Worker 
184*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = OT_ERROR_NONE);
185*cfb92d14SAndroid Build Coastguard Worker     }
186*cfb92d14SAndroid Build Coastguard Worker 
187*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
188*cfb92d14SAndroid Build Coastguard Worker 
189*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(discerner);
190*cfb92d14SAndroid Build Coastguard Worker 
191*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[1] == "*")
192*cfb92d14SAndroid Build Coastguard Worker     {
193*cfb92d14SAndroid Build Coastguard Worker         // Intentionally empty
194*cfb92d14SAndroid Build Coastguard Worker     }
195*cfb92d14SAndroid Build Coastguard Worker     else
196*cfb92d14SAndroid Build Coastguard Worker     {
197*cfb92d14SAndroid Build Coastguard Worker         error = ParseJoinerDiscerner(aArgs[1], discerner);
198*cfb92d14SAndroid Build Coastguard Worker 
199*cfb92d14SAndroid Build Coastguard Worker         if (error == OT_ERROR_NOT_FOUND)
200*cfb92d14SAndroid Build Coastguard Worker         {
201*cfb92d14SAndroid Build Coastguard Worker             error   = aArgs[1].ParseAsHexString(addr.m8);
202*cfb92d14SAndroid Build Coastguard Worker             addrPtr = &addr;
203*cfb92d14SAndroid Build Coastguard Worker         }
204*cfb92d14SAndroid Build Coastguard Worker 
205*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error);
206*cfb92d14SAndroid Build Coastguard Worker     }
207*cfb92d14SAndroid Build Coastguard Worker 
208*cfb92d14SAndroid Build Coastguard Worker     /**
209*cfb92d14SAndroid Build Coastguard Worker      * @cli commissioner joiner add
210*cfb92d14SAndroid Build Coastguard Worker      * @code
211*cfb92d14SAndroid Build Coastguard Worker      * commissioner joiner add d45e64fa83f81cf7 J01NME
212*cfb92d14SAndroid Build Coastguard Worker      * Done
213*cfb92d14SAndroid Build Coastguard Worker      * @endcode
214*cfb92d14SAndroid Build Coastguard Worker      * @code
215*cfb92d14SAndroid Build Coastguard Worker      * commissioner joiner add 0xabc/12 J01NME
216*cfb92d14SAndroid Build Coastguard Worker      * Done
217*cfb92d14SAndroid Build Coastguard Worker      * @endcode
218*cfb92d14SAndroid Build Coastguard Worker      * @cparam commissioner joiner add @ca{eui64}|@ca{discerner pksd} [@ca{timeout}]
219*cfb92d14SAndroid Build Coastguard Worker      *   * `eui64`: IEEE EUI-64 of the %Joiner. To match any joiner, use `*`.
220*cfb92d14SAndroid Build Coastguard Worker      *   * `discerner`: The %Joiner discerner in the format `number/length`.
221*cfb92d14SAndroid Build Coastguard Worker      *   * `pksd`: Pre-Shared Key for the joiner.
222*cfb92d14SAndroid Build Coastguard Worker      *   * `timeout`: The %Joiner timeout in seconds.
223*cfb92d14SAndroid Build Coastguard Worker      * @par
224*cfb92d14SAndroid Build Coastguard Worker      * Adds a joiner entry.
225*cfb92d14SAndroid Build Coastguard Worker      * @note Use this command only after successfully starting the %Commissioner role
226*cfb92d14SAndroid Build Coastguard Worker      * with the `commissioner start` command.
227*cfb92d14SAndroid Build Coastguard Worker      * @csa{commissioner start}
228*cfb92d14SAndroid Build Coastguard Worker      * @sa otCommissionerAddJoiner
229*cfb92d14SAndroid Build Coastguard Worker      * @sa otCommissionerAddJoinerWithDiscerner
230*cfb92d14SAndroid Build Coastguard Worker      */
231*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0] == "add")
232*cfb92d14SAndroid Build Coastguard Worker     {
233*cfb92d14SAndroid Build Coastguard Worker         uint32_t timeout = kDefaultJoinerTimeout;
234*cfb92d14SAndroid Build Coastguard Worker 
235*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(!aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
236*cfb92d14SAndroid Build Coastguard Worker 
237*cfb92d14SAndroid Build Coastguard Worker         if (!aArgs[3].IsEmpty())
238*cfb92d14SAndroid Build Coastguard Worker         {
239*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[3].ParseAsUint32(timeout));
240*cfb92d14SAndroid Build Coastguard Worker         }
241*cfb92d14SAndroid Build Coastguard Worker 
242*cfb92d14SAndroid Build Coastguard Worker         if (discerner.mLength)
243*cfb92d14SAndroid Build Coastguard Worker         {
244*cfb92d14SAndroid Build Coastguard Worker             error = otCommissionerAddJoinerWithDiscerner(GetInstancePtr(), &discerner, aArgs[2].GetCString(), timeout);
245*cfb92d14SAndroid Build Coastguard Worker         }
246*cfb92d14SAndroid Build Coastguard Worker         else
247*cfb92d14SAndroid Build Coastguard Worker         {
248*cfb92d14SAndroid Build Coastguard Worker             error = otCommissionerAddJoiner(GetInstancePtr(), addrPtr, aArgs[2].GetCString(), timeout);
249*cfb92d14SAndroid Build Coastguard Worker         }
250*cfb92d14SAndroid Build Coastguard Worker         /**
251*cfb92d14SAndroid Build Coastguard Worker          * @cli commissioner joiner remove
252*cfb92d14SAndroid Build Coastguard Worker          * @code
253*cfb92d14SAndroid Build Coastguard Worker          * commissioner joiner remove d45e64fa83f81cf7
254*cfb92d14SAndroid Build Coastguard Worker          * Done
255*cfb92d14SAndroid Build Coastguard Worker          * @endcode
256*cfb92d14SAndroid Build Coastguard Worker          * @code
257*cfb92d14SAndroid Build Coastguard Worker          * commissioner joiner remove 0xabc/12
258*cfb92d14SAndroid Build Coastguard Worker          * Done
259*cfb92d14SAndroid Build Coastguard Worker          * @endcode
260*cfb92d14SAndroid Build Coastguard Worker          * @cparam commissioner joiner remove @ca{eui64}|@ca{discerner}
261*cfb92d14SAndroid Build Coastguard Worker          *   * `eui64`: IEEE EUI-64 of the joiner. To match any joiner, use `*`.
262*cfb92d14SAndroid Build Coastguard Worker          *   * `discerner`: The joiner discerner in the format `number/length`.
263*cfb92d14SAndroid Build Coastguard Worker          * @par
264*cfb92d14SAndroid Build Coastguard Worker          * Removes a %Joiner entry.
265*cfb92d14SAndroid Build Coastguard Worker          * @note Use this command only after successfully starting the %Commissioner role
266*cfb92d14SAndroid Build Coastguard Worker          * with the `commissioner start` command.
267*cfb92d14SAndroid Build Coastguard Worker          * @csa{commissioner start}
268*cfb92d14SAndroid Build Coastguard Worker          * @sa otCommissionerRemoveJoiner
269*cfb92d14SAndroid Build Coastguard Worker          * @sa otCommissionerRemoveJoinerWithDiscerner
270*cfb92d14SAndroid Build Coastguard Worker          */
271*cfb92d14SAndroid Build Coastguard Worker     }
272*cfb92d14SAndroid Build Coastguard Worker     else if (aArgs[0] == "remove")
273*cfb92d14SAndroid Build Coastguard Worker     {
274*cfb92d14SAndroid Build Coastguard Worker         if (discerner.mLength)
275*cfb92d14SAndroid Build Coastguard Worker         {
276*cfb92d14SAndroid Build Coastguard Worker             error = otCommissionerRemoveJoinerWithDiscerner(GetInstancePtr(), &discerner);
277*cfb92d14SAndroid Build Coastguard Worker         }
278*cfb92d14SAndroid Build Coastguard Worker         else
279*cfb92d14SAndroid Build Coastguard Worker         {
280*cfb92d14SAndroid Build Coastguard Worker             error = otCommissionerRemoveJoiner(GetInstancePtr(), addrPtr);
281*cfb92d14SAndroid Build Coastguard Worker         }
282*cfb92d14SAndroid Build Coastguard Worker     }
283*cfb92d14SAndroid Build Coastguard Worker     else
284*cfb92d14SAndroid Build Coastguard Worker     {
285*cfb92d14SAndroid Build Coastguard Worker         error = OT_ERROR_INVALID_ARGS;
286*cfb92d14SAndroid Build Coastguard Worker     }
287*cfb92d14SAndroid Build Coastguard Worker 
288*cfb92d14SAndroid Build Coastguard Worker exit:
289*cfb92d14SAndroid Build Coastguard Worker     return error;
290*cfb92d14SAndroid Build Coastguard Worker }
291*cfb92d14SAndroid Build Coastguard Worker 
292*cfb92d14SAndroid Build Coastguard Worker /**
293*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner mgmtget
294*cfb92d14SAndroid Build Coastguard Worker  * @code
295*cfb92d14SAndroid Build Coastguard Worker  * commissioner mgmtget locator sessionid
296*cfb92d14SAndroid Build Coastguard Worker  * Done
297*cfb92d14SAndroid Build Coastguard Worker  * @endcode
298*cfb92d14SAndroid Build Coastguard Worker  * @cparam commissioner mgmtget [locator] [sessionid] <!--
299*cfb92d14SAndroid Build Coastguard Worker  * -->                          [steeringdata] [joinerudpport] <!--
300*cfb92d14SAndroid Build Coastguard Worker  * -->                          [-x @ca{TLVs}]
301*cfb92d14SAndroid Build Coastguard Worker  *   * `locator`: Border Router RLOC16.
302*cfb92d14SAndroid Build Coastguard Worker  *   * `sessionid`: Session ID of the %Commissioner.
303*cfb92d14SAndroid Build Coastguard Worker  *   * `steeringdata`: Steering data.
304*cfb92d14SAndroid Build Coastguard Worker  *   * `joinerudpport`: %Joiner UDP port.
305*cfb92d14SAndroid Build Coastguard Worker  *   * `TLVs`: The set of TLVs to be retrieved.
306*cfb92d14SAndroid Build Coastguard Worker  * @par
307*cfb92d14SAndroid Build Coastguard Worker  * Sends a `MGMT_GET` (Management Get) message to the Leader.
308*cfb92d14SAndroid Build Coastguard Worker  * Variable values that have been set using the `commissioner mgmtset` command are returned.
309*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerSendMgmtGet
310*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])311*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("mgmtget")>(Arg aArgs[])
312*cfb92d14SAndroid Build Coastguard Worker {
313*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
314*cfb92d14SAndroid Build Coastguard Worker     uint8_t tlvs[32];
315*cfb92d14SAndroid Build Coastguard Worker     uint8_t length = 0;
316*cfb92d14SAndroid Build Coastguard Worker 
317*cfb92d14SAndroid Build Coastguard Worker     for (; !aArgs->IsEmpty(); aArgs++)
318*cfb92d14SAndroid Build Coastguard Worker     {
319*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(static_cast<size_t>(length) < sizeof(tlvs), error = OT_ERROR_NO_BUFS);
320*cfb92d14SAndroid Build Coastguard Worker 
321*cfb92d14SAndroid Build Coastguard Worker         if (*aArgs == "locator")
322*cfb92d14SAndroid Build Coastguard Worker         {
323*cfb92d14SAndroid Build Coastguard Worker             tlvs[length++] = OT_MESHCOP_TLV_BORDER_AGENT_RLOC;
324*cfb92d14SAndroid Build Coastguard Worker         }
325*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "sessionid")
326*cfb92d14SAndroid Build Coastguard Worker         {
327*cfb92d14SAndroid Build Coastguard Worker             tlvs[length++] = OT_MESHCOP_TLV_COMM_SESSION_ID;
328*cfb92d14SAndroid Build Coastguard Worker         }
329*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "steeringdata")
330*cfb92d14SAndroid Build Coastguard Worker         {
331*cfb92d14SAndroid Build Coastguard Worker             tlvs[length++] = OT_MESHCOP_TLV_STEERING_DATA;
332*cfb92d14SAndroid Build Coastguard Worker         }
333*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "joinerudpport")
334*cfb92d14SAndroid Build Coastguard Worker         {
335*cfb92d14SAndroid Build Coastguard Worker             tlvs[length++] = OT_MESHCOP_TLV_JOINER_UDP_PORT;
336*cfb92d14SAndroid Build Coastguard Worker         }
337*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "-x")
338*cfb92d14SAndroid Build Coastguard Worker         {
339*cfb92d14SAndroid Build Coastguard Worker             uint16_t readLength;
340*cfb92d14SAndroid Build Coastguard Worker 
341*cfb92d14SAndroid Build Coastguard Worker             aArgs++;
342*cfb92d14SAndroid Build Coastguard Worker             readLength = static_cast<uint16_t>(sizeof(tlvs) - length);
343*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs->ParseAsHexString(readLength, tlvs + length));
344*cfb92d14SAndroid Build Coastguard Worker             length += static_cast<uint8_t>(readLength);
345*cfb92d14SAndroid Build Coastguard Worker         }
346*cfb92d14SAndroid Build Coastguard Worker         else
347*cfb92d14SAndroid Build Coastguard Worker         {
348*cfb92d14SAndroid Build Coastguard Worker             ExitNow(error = OT_ERROR_INVALID_ARGS);
349*cfb92d14SAndroid Build Coastguard Worker         }
350*cfb92d14SAndroid Build Coastguard Worker     }
351*cfb92d14SAndroid Build Coastguard Worker 
352*cfb92d14SAndroid Build Coastguard Worker     error = otCommissionerSendMgmtGet(GetInstancePtr(), tlvs, static_cast<uint8_t>(length));
353*cfb92d14SAndroid Build Coastguard Worker 
354*cfb92d14SAndroid Build Coastguard Worker exit:
355*cfb92d14SAndroid Build Coastguard Worker     return error;
356*cfb92d14SAndroid Build Coastguard Worker }
357*cfb92d14SAndroid Build Coastguard Worker 
358*cfb92d14SAndroid Build Coastguard Worker /**
359*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner mgmtset
360*cfb92d14SAndroid Build Coastguard Worker  * @code
361*cfb92d14SAndroid Build Coastguard Worker  * commissioner mgmtset joinerudpport 9988
362*cfb92d14SAndroid Build Coastguard Worker  * Done
363*cfb92d14SAndroid Build Coastguard Worker  * @endcode
364*cfb92d14SAndroid Build Coastguard Worker  * @cparam commissioner mgmtset [locator @ca{locator}] [sessionid @ca{sessionid}] <!--
365*cfb92d14SAndroid Build Coastguard Worker  * -->                          [steeringdata @ca{steeringdata}] [joinerudpport @ca{joinerudpport}] <!--
366*cfb92d14SAndroid Build Coastguard Worker  * -->                          [-x @ca{TLVs}]
367*cfb92d14SAndroid Build Coastguard Worker  *   * `locator`: Border Router RLOC16.
368*cfb92d14SAndroid Build Coastguard Worker  *   * `sessionid`: Session ID of the %Commissioner.
369*cfb92d14SAndroid Build Coastguard Worker  *   * `steeringdata`: Steering data.
370*cfb92d14SAndroid Build Coastguard Worker  *   * `joinerudpport`: %Joiner UDP port.
371*cfb92d14SAndroid Build Coastguard Worker  *   * `TLVs`: The set of TLVs to be retrieved.
372*cfb92d14SAndroid Build Coastguard Worker  * @par
373*cfb92d14SAndroid Build Coastguard Worker  * Sends a `MGMT_SET` (Management Set) message to the Leader, and sets the
374*cfb92d14SAndroid Build Coastguard Worker  * variables to the values specified.
375*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerSendMgmtSet
376*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])377*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("mgmtset")>(Arg aArgs[])
378*cfb92d14SAndroid Build Coastguard Worker {
379*cfb92d14SAndroid Build Coastguard Worker     otError                error;
380*cfb92d14SAndroid Build Coastguard Worker     otCommissioningDataset dataset;
381*cfb92d14SAndroid Build Coastguard Worker     uint8_t                tlvs[32];
382*cfb92d14SAndroid Build Coastguard Worker     uint8_t                tlvsLength = 0;
383*cfb92d14SAndroid Build Coastguard Worker 
384*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
385*cfb92d14SAndroid Build Coastguard Worker 
386*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(dataset);
387*cfb92d14SAndroid Build Coastguard Worker 
388*cfb92d14SAndroid Build Coastguard Worker     for (; !aArgs->IsEmpty(); aArgs++)
389*cfb92d14SAndroid Build Coastguard Worker     {
390*cfb92d14SAndroid Build Coastguard Worker         if (*aArgs == "locator")
391*cfb92d14SAndroid Build Coastguard Worker         {
392*cfb92d14SAndroid Build Coastguard Worker             aArgs++;
393*cfb92d14SAndroid Build Coastguard Worker             dataset.mIsLocatorSet = true;
394*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs->ParseAsUint16(dataset.mLocator));
395*cfb92d14SAndroid Build Coastguard Worker         }
396*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "sessionid")
397*cfb92d14SAndroid Build Coastguard Worker         {
398*cfb92d14SAndroid Build Coastguard Worker             aArgs++;
399*cfb92d14SAndroid Build Coastguard Worker             dataset.mIsSessionIdSet = true;
400*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs->ParseAsUint16(dataset.mSessionId));
401*cfb92d14SAndroid Build Coastguard Worker         }
402*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "steeringdata")
403*cfb92d14SAndroid Build Coastguard Worker         {
404*cfb92d14SAndroid Build Coastguard Worker             uint16_t length;
405*cfb92d14SAndroid Build Coastguard Worker 
406*cfb92d14SAndroid Build Coastguard Worker             aArgs++;
407*cfb92d14SAndroid Build Coastguard Worker             dataset.mIsSteeringDataSet = true;
408*cfb92d14SAndroid Build Coastguard Worker             length                     = sizeof(dataset.mSteeringData.m8);
409*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs->ParseAsHexString(length, dataset.mSteeringData.m8));
410*cfb92d14SAndroid Build Coastguard Worker             dataset.mSteeringData.mLength = static_cast<uint8_t>(length);
411*cfb92d14SAndroid Build Coastguard Worker         }
412*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "joinerudpport")
413*cfb92d14SAndroid Build Coastguard Worker         {
414*cfb92d14SAndroid Build Coastguard Worker             aArgs++;
415*cfb92d14SAndroid Build Coastguard Worker             dataset.mIsJoinerUdpPortSet = true;
416*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs->ParseAsUint16(dataset.mJoinerUdpPort));
417*cfb92d14SAndroid Build Coastguard Worker         }
418*cfb92d14SAndroid Build Coastguard Worker         else if (*aArgs == "-x")
419*cfb92d14SAndroid Build Coastguard Worker         {
420*cfb92d14SAndroid Build Coastguard Worker             uint16_t length;
421*cfb92d14SAndroid Build Coastguard Worker 
422*cfb92d14SAndroid Build Coastguard Worker             aArgs++;
423*cfb92d14SAndroid Build Coastguard Worker             length = sizeof(tlvs);
424*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs->ParseAsHexString(length, tlvs));
425*cfb92d14SAndroid Build Coastguard Worker             tlvsLength = static_cast<uint8_t>(length);
426*cfb92d14SAndroid Build Coastguard Worker         }
427*cfb92d14SAndroid Build Coastguard Worker         else
428*cfb92d14SAndroid Build Coastguard Worker         {
429*cfb92d14SAndroid Build Coastguard Worker             ExitNow(error = OT_ERROR_INVALID_ARGS);
430*cfb92d14SAndroid Build Coastguard Worker         }
431*cfb92d14SAndroid Build Coastguard Worker     }
432*cfb92d14SAndroid Build Coastguard Worker 
433*cfb92d14SAndroid Build Coastguard Worker     error = otCommissionerSendMgmtSet(GetInstancePtr(), &dataset, tlvs, tlvsLength);
434*cfb92d14SAndroid Build Coastguard Worker 
435*cfb92d14SAndroid Build Coastguard Worker exit:
436*cfb92d14SAndroid Build Coastguard Worker     return error;
437*cfb92d14SAndroid Build Coastguard Worker }
438*cfb92d14SAndroid Build Coastguard Worker 
439*cfb92d14SAndroid Build Coastguard Worker /**
440*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner panid
441*cfb92d14SAndroid Build Coastguard Worker  * @code
442*cfb92d14SAndroid Build Coastguard Worker  * commissioner panid 0xdead 0x7fff800 fdde:ad00:beef:0:0:ff:fe00:c00
443*cfb92d14SAndroid Build Coastguard Worker  * Done
444*cfb92d14SAndroid Build Coastguard Worker  * Conflict: dead, 00000800
445*cfb92d14SAndroid Build Coastguard Worker  * @endcode
446*cfb92d14SAndroid Build Coastguard Worker  * @cparam commissioner panid @ca{panid} @ca{mask} @ca{destination}
447*cfb92d14SAndroid Build Coastguard Worker  *   * `paind`: PAN ID to use to check for conflicts.
448*cfb92d14SAndroid Build Coastguard Worker  *   * `mask`; Bitmask that identifies channels to perform IEEE 802.15.4
449*cfb92d14SAndroid Build Coastguard Worker  *     Active Scans.
450*cfb92d14SAndroid Build Coastguard Worker  *   * `destination`: IPv6 destination address for the message. The message may be multicast.
451*cfb92d14SAndroid Build Coastguard Worker  * @par
452*cfb92d14SAndroid Build Coastguard Worker  * Sends a PAN ID query. Command output is returned as it is received.
453*cfb92d14SAndroid Build Coastguard Worker  * @note Use this command only after successfully starting the %Commissioner role
454*cfb92d14SAndroid Build Coastguard Worker  * with the `commissioner start` command.
455*cfb92d14SAndroid Build Coastguard Worker  * @csa{commissioner start}
456*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerPanIdQuery
457*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])458*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("panid")>(Arg aArgs[])
459*cfb92d14SAndroid Build Coastguard Worker {
460*cfb92d14SAndroid Build Coastguard Worker     otError      error;
461*cfb92d14SAndroid Build Coastguard Worker     uint16_t     panId;
462*cfb92d14SAndroid Build Coastguard Worker     uint32_t     mask;
463*cfb92d14SAndroid Build Coastguard Worker     otIp6Address address;
464*cfb92d14SAndroid Build Coastguard Worker 
465*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[0].ParseAsUint16(panId));
466*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[1].ParseAsUint32(mask));
467*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[2].ParseAsIp6Address(address));
468*cfb92d14SAndroid Build Coastguard Worker 
469*cfb92d14SAndroid Build Coastguard Worker     error = otCommissionerPanIdQuery(GetInstancePtr(), panId, mask, &address, &Commissioner::HandlePanIdConflict, this);
470*cfb92d14SAndroid Build Coastguard Worker 
471*cfb92d14SAndroid Build Coastguard Worker exit:
472*cfb92d14SAndroid Build Coastguard Worker     return error;
473*cfb92d14SAndroid Build Coastguard Worker }
474*cfb92d14SAndroid Build Coastguard Worker 
475*cfb92d14SAndroid Build Coastguard Worker /**
476*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner provisioningurl
477*cfb92d14SAndroid Build Coastguard Worker  * @code
478*cfb92d14SAndroid Build Coastguard Worker  * commissioner provisioningurl http://github.com/openthread/openthread
479*cfb92d14SAndroid Build Coastguard Worker  * Done
480*cfb92d14SAndroid Build Coastguard Worker  * @endcode
481*cfb92d14SAndroid Build Coastguard Worker  * @cparam commissioner provisioningurl @ca{provisioningurl}
482*cfb92d14SAndroid Build Coastguard Worker  * @par
483*cfb92d14SAndroid Build Coastguard Worker  * Sets the %Commissioner provisioning URL.
484*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerSetProvisioningUrl
485*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])486*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("provisioningurl")>(Arg aArgs[])
487*cfb92d14SAndroid Build Coastguard Worker {
488*cfb92d14SAndroid Build Coastguard Worker     // If aArgs[0] is empty, `GetCString() will return `nullptr`
489*cfb92d14SAndroid Build Coastguard Worker     /// which will correctly clear the provisioning URL.
490*cfb92d14SAndroid Build Coastguard Worker     return otCommissionerSetProvisioningUrl(GetInstancePtr(), aArgs[0].GetCString());
491*cfb92d14SAndroid Build Coastguard Worker }
492*cfb92d14SAndroid Build Coastguard Worker 
493*cfb92d14SAndroid Build Coastguard Worker /**
494*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner sessionid
495*cfb92d14SAndroid Build Coastguard Worker  * @code
496*cfb92d14SAndroid Build Coastguard Worker  * commissioner sessionid
497*cfb92d14SAndroid Build Coastguard Worker  * 0
498*cfb92d14SAndroid Build Coastguard Worker  * Done
499*cfb92d14SAndroid Build Coastguard Worker  * @endcode
500*cfb92d14SAndroid Build Coastguard Worker  * @par
501*cfb92d14SAndroid Build Coastguard Worker  * Gets the current %Commissioner session ID.
502*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerGetSessionId
503*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])504*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("sessionid")>(Arg aArgs[])
505*cfb92d14SAndroid Build Coastguard Worker {
506*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aArgs);
507*cfb92d14SAndroid Build Coastguard Worker 
508*cfb92d14SAndroid Build Coastguard Worker     OutputLine("%d", otCommissionerGetSessionId(GetInstancePtr()));
509*cfb92d14SAndroid Build Coastguard Worker 
510*cfb92d14SAndroid Build Coastguard Worker     return OT_ERROR_NONE;
511*cfb92d14SAndroid Build Coastguard Worker }
512*cfb92d14SAndroid Build Coastguard Worker 
513*cfb92d14SAndroid Build Coastguard Worker /**
514*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner id (get,set)
515*cfb92d14SAndroid Build Coastguard Worker  * @code
516*cfb92d14SAndroid Build Coastguard Worker  * commissioner id OpenThread Commissioner
517*cfb92d14SAndroid Build Coastguard Worker  * Done
518*cfb92d14SAndroid Build Coastguard Worker  * @endcode
519*cfb92d14SAndroid Build Coastguard Worker  * @code
520*cfb92d14SAndroid Build Coastguard Worker  * commissioner id
521*cfb92d14SAndroid Build Coastguard Worker  * OpenThread Commissioner
522*cfb92d14SAndroid Build Coastguard Worker  * Done
523*cfb92d14SAndroid Build Coastguard Worker  * @endcode
524*cfb92d14SAndroid Build Coastguard Worker  * @cparam commissioner id @ca{name}
525*cfb92d14SAndroid Build Coastguard Worker  * @par
526*cfb92d14SAndroid Build Coastguard Worker  * Gets or sets the OpenThread %Commissioner ID name.
527*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerSetId
528*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])529*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("id")>(Arg aArgs[])
530*cfb92d14SAndroid Build Coastguard Worker {
531*cfb92d14SAndroid Build Coastguard Worker     otError error;
532*cfb92d14SAndroid Build Coastguard Worker 
533*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0].IsEmpty())
534*cfb92d14SAndroid Build Coastguard Worker     {
535*cfb92d14SAndroid Build Coastguard Worker         OutputLine("%s", otCommissionerGetId(GetInstancePtr()));
536*cfb92d14SAndroid Build Coastguard Worker         error = OT_ERROR_NONE;
537*cfb92d14SAndroid Build Coastguard Worker     }
538*cfb92d14SAndroid Build Coastguard Worker     else
539*cfb92d14SAndroid Build Coastguard Worker     {
540*cfb92d14SAndroid Build Coastguard Worker         error = otCommissionerSetId(GetInstancePtr(), aArgs[0].GetCString());
541*cfb92d14SAndroid Build Coastguard Worker     }
542*cfb92d14SAndroid Build Coastguard Worker 
543*cfb92d14SAndroid Build Coastguard Worker     return error;
544*cfb92d14SAndroid Build Coastguard Worker }
545*cfb92d14SAndroid Build Coastguard Worker 
546*cfb92d14SAndroid Build Coastguard Worker /**
547*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner start
548*cfb92d14SAndroid Build Coastguard Worker  * @code
549*cfb92d14SAndroid Build Coastguard Worker  * commissioner start
550*cfb92d14SAndroid Build Coastguard Worker  * Commissioner: petitioning
551*cfb92d14SAndroid Build Coastguard Worker  * Done
552*cfb92d14SAndroid Build Coastguard Worker  * Commissioner: active
553*cfb92d14SAndroid Build Coastguard Worker  * @endcode
554*cfb92d14SAndroid Build Coastguard Worker  * @par
555*cfb92d14SAndroid Build Coastguard Worker  * Starts the Thread %Commissioner role.
556*cfb92d14SAndroid Build Coastguard Worker  * @note The `commissioner` commands are available only when
557*cfb92d14SAndroid Build Coastguard Worker  * `OPENTHREAD_CONFIG_COMMISSIONER_ENABLE` and `OPENTHREAD_FTD` are set.
558*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerStart
559*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])560*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("start")>(Arg aArgs[])
561*cfb92d14SAndroid Build Coastguard Worker {
562*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aArgs);
563*cfb92d14SAndroid Build Coastguard Worker 
564*cfb92d14SAndroid Build Coastguard Worker     return otCommissionerStart(GetInstancePtr(), &Commissioner::HandleStateChanged, &Commissioner::HandleJoinerEvent,
565*cfb92d14SAndroid Build Coastguard Worker                                this);
566*cfb92d14SAndroid Build Coastguard Worker }
567*cfb92d14SAndroid Build Coastguard Worker 
HandleStateChanged(otCommissionerState aState,void * aContext)568*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandleStateChanged(otCommissionerState aState, void *aContext)
569*cfb92d14SAndroid Build Coastguard Worker {
570*cfb92d14SAndroid Build Coastguard Worker     static_cast<Commissioner *>(aContext)->HandleStateChanged(aState);
571*cfb92d14SAndroid Build Coastguard Worker }
572*cfb92d14SAndroid Build Coastguard Worker 
HandleStateChanged(otCommissionerState aState)573*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandleStateChanged(otCommissionerState aState)
574*cfb92d14SAndroid Build Coastguard Worker {
575*cfb92d14SAndroid Build Coastguard Worker     OutputLine("Commissioner: %s", StateToString(aState));
576*cfb92d14SAndroid Build Coastguard Worker }
577*cfb92d14SAndroid Build Coastguard Worker 
StateToString(otCommissionerState aState)578*cfb92d14SAndroid Build Coastguard Worker const char *Commissioner::StateToString(otCommissionerState aState)
579*cfb92d14SAndroid Build Coastguard Worker {
580*cfb92d14SAndroid Build Coastguard Worker     static const char *const kStateString[] = {
581*cfb92d14SAndroid Build Coastguard Worker         "disabled",    // (0) OT_COMMISSIONER_STATE_DISABLED
582*cfb92d14SAndroid Build Coastguard Worker         "petitioning", // (1) OT_COMMISSIONER_STATE_PETITION
583*cfb92d14SAndroid Build Coastguard Worker         "active",      // (2) OT_COMMISSIONER_STATE_ACTIVE
584*cfb92d14SAndroid Build Coastguard Worker     };
585*cfb92d14SAndroid Build Coastguard Worker 
586*cfb92d14SAndroid Build Coastguard Worker     static_assert(0 == OT_COMMISSIONER_STATE_DISABLED, "OT_COMMISSIONER_STATE_DISABLED value is incorrect");
587*cfb92d14SAndroid Build Coastguard Worker     static_assert(1 == OT_COMMISSIONER_STATE_PETITION, "OT_COMMISSIONER_STATE_PETITION value is incorrect");
588*cfb92d14SAndroid Build Coastguard Worker     static_assert(2 == OT_COMMISSIONER_STATE_ACTIVE, "OT_COMMISSIONER_STATE_ACTIVE value is incorrect");
589*cfb92d14SAndroid Build Coastguard Worker 
590*cfb92d14SAndroid Build Coastguard Worker     return Stringify(aState, kStateString);
591*cfb92d14SAndroid Build Coastguard Worker }
592*cfb92d14SAndroid Build Coastguard Worker 
HandleJoinerEvent(otCommissionerJoinerEvent aEvent,const otJoinerInfo * aJoinerInfo,const otExtAddress * aJoinerId,void * aContext)593*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandleJoinerEvent(otCommissionerJoinerEvent aEvent,
594*cfb92d14SAndroid Build Coastguard Worker                                      const otJoinerInfo       *aJoinerInfo,
595*cfb92d14SAndroid Build Coastguard Worker                                      const otExtAddress       *aJoinerId,
596*cfb92d14SAndroid Build Coastguard Worker                                      void                     *aContext)
597*cfb92d14SAndroid Build Coastguard Worker {
598*cfb92d14SAndroid Build Coastguard Worker     static_cast<Commissioner *>(aContext)->HandleJoinerEvent(aEvent, aJoinerInfo, aJoinerId);
599*cfb92d14SAndroid Build Coastguard Worker }
600*cfb92d14SAndroid Build Coastguard Worker 
HandleJoinerEvent(otCommissionerJoinerEvent aEvent,const otJoinerInfo * aJoinerInfo,const otExtAddress * aJoinerId)601*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandleJoinerEvent(otCommissionerJoinerEvent aEvent,
602*cfb92d14SAndroid Build Coastguard Worker                                      const otJoinerInfo       *aJoinerInfo,
603*cfb92d14SAndroid Build Coastguard Worker                                      const otExtAddress       *aJoinerId)
604*cfb92d14SAndroid Build Coastguard Worker {
605*cfb92d14SAndroid Build Coastguard Worker     static const char *const kEventStrings[] = {
606*cfb92d14SAndroid Build Coastguard Worker         "start",    // (0) OT_COMMISSIONER_JOINER_START
607*cfb92d14SAndroid Build Coastguard Worker         "connect",  // (1) OT_COMMISSIONER_JOINER_CONNECTED
608*cfb92d14SAndroid Build Coastguard Worker         "finalize", // (2) OT_COMMISSIONER_JOINER_FINALIZE
609*cfb92d14SAndroid Build Coastguard Worker         "end",      // (3) OT_COMMISSIONER_JOINER_END
610*cfb92d14SAndroid Build Coastguard Worker         "remove",   // (4) OT_COMMISSIONER_JOINER_REMOVED
611*cfb92d14SAndroid Build Coastguard Worker     };
612*cfb92d14SAndroid Build Coastguard Worker 
613*cfb92d14SAndroid Build Coastguard Worker     static_assert(0 == OT_COMMISSIONER_JOINER_START, "OT_COMMISSIONER_JOINER_START value is incorrect");
614*cfb92d14SAndroid Build Coastguard Worker     static_assert(1 == OT_COMMISSIONER_JOINER_CONNECTED, "OT_COMMISSIONER_JOINER_CONNECTED value is incorrect");
615*cfb92d14SAndroid Build Coastguard Worker     static_assert(2 == OT_COMMISSIONER_JOINER_FINALIZE, "OT_COMMISSIONER_JOINER_FINALIZE value is incorrect");
616*cfb92d14SAndroid Build Coastguard Worker     static_assert(3 == OT_COMMISSIONER_JOINER_END, "OT_COMMISSIONER_JOINER_END value is incorrect");
617*cfb92d14SAndroid Build Coastguard Worker     static_assert(4 == OT_COMMISSIONER_JOINER_REMOVED, "OT_COMMISSIONER_JOINER_REMOVED value is incorrect");
618*cfb92d14SAndroid Build Coastguard Worker 
619*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aJoinerInfo);
620*cfb92d14SAndroid Build Coastguard Worker 
621*cfb92d14SAndroid Build Coastguard Worker     OutputFormat("Commissioner: Joiner %s ", Stringify(aEvent, kEventStrings));
622*cfb92d14SAndroid Build Coastguard Worker 
623*cfb92d14SAndroid Build Coastguard Worker     if (aJoinerId != nullptr)
624*cfb92d14SAndroid Build Coastguard Worker     {
625*cfb92d14SAndroid Build Coastguard Worker         OutputExtAddress(*aJoinerId);
626*cfb92d14SAndroid Build Coastguard Worker     }
627*cfb92d14SAndroid Build Coastguard Worker 
628*cfb92d14SAndroid Build Coastguard Worker     OutputNewLine();
629*cfb92d14SAndroid Build Coastguard Worker }
630*cfb92d14SAndroid Build Coastguard Worker 
631*cfb92d14SAndroid Build Coastguard Worker /**
632*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner stop
633*cfb92d14SAndroid Build Coastguard Worker  * @code
634*cfb92d14SAndroid Build Coastguard Worker  * commissioner stop
635*cfb92d14SAndroid Build Coastguard Worker  * Done
636*cfb92d14SAndroid Build Coastguard Worker  * @endcode
637*cfb92d14SAndroid Build Coastguard Worker  * @par
638*cfb92d14SAndroid Build Coastguard Worker  * Stops the Thread %Commissioner role.
639*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerStop
640*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])641*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("stop")>(Arg aArgs[])
642*cfb92d14SAndroid Build Coastguard Worker {
643*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aArgs);
644*cfb92d14SAndroid Build Coastguard Worker 
645*cfb92d14SAndroid Build Coastguard Worker     return otCommissionerStop(GetInstancePtr());
646*cfb92d14SAndroid Build Coastguard Worker }
647*cfb92d14SAndroid Build Coastguard Worker 
648*cfb92d14SAndroid Build Coastguard Worker /**
649*cfb92d14SAndroid Build Coastguard Worker  * @cli commissioner state
650*cfb92d14SAndroid Build Coastguard Worker  * @code
651*cfb92d14SAndroid Build Coastguard Worker  * commissioner state
652*cfb92d14SAndroid Build Coastguard Worker  * active
653*cfb92d14SAndroid Build Coastguard Worker  * Done
654*cfb92d14SAndroid Build Coastguard Worker  * @endcode
655*cfb92d14SAndroid Build Coastguard Worker  * @par
656*cfb92d14SAndroid Build Coastguard Worker  * Returns the current state of the %Commissioner. Possible values are
657*cfb92d14SAndroid Build Coastguard Worker  * `active`, `disabled`, or `petition` (petitioning to become %Commissioner).
658*cfb92d14SAndroid Build Coastguard Worker  * @sa otCommissionerState
659*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])660*cfb92d14SAndroid Build Coastguard Worker template <> otError Commissioner::Process<Cmd("state")>(Arg aArgs[])
661*cfb92d14SAndroid Build Coastguard Worker {
662*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aArgs);
663*cfb92d14SAndroid Build Coastguard Worker 
664*cfb92d14SAndroid Build Coastguard Worker     OutputLine("%s", StateToString(otCommissionerGetState(GetInstancePtr())));
665*cfb92d14SAndroid Build Coastguard Worker 
666*cfb92d14SAndroid Build Coastguard Worker     return OT_ERROR_NONE;
667*cfb92d14SAndroid Build Coastguard Worker }
668*cfb92d14SAndroid Build Coastguard Worker 
Process(Arg aArgs[])669*cfb92d14SAndroid Build Coastguard Worker otError Commissioner::Process(Arg aArgs[])
670*cfb92d14SAndroid Build Coastguard Worker {
671*cfb92d14SAndroid Build Coastguard Worker #define CmdEntry(aCommandString)                                    \
672*cfb92d14SAndroid Build Coastguard Worker     {                                                               \
673*cfb92d14SAndroid Build Coastguard Worker         aCommandString, &Commissioner::Process<Cmd(aCommandString)> \
674*cfb92d14SAndroid Build Coastguard Worker     }
675*cfb92d14SAndroid Build Coastguard Worker 
676*cfb92d14SAndroid Build Coastguard Worker     static constexpr Command kCommands[] = {
677*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("announce"),  CmdEntry("energy"),  CmdEntry("id"),    CmdEntry("joiner"),
678*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("mgmtget"),   CmdEntry("mgmtset"), CmdEntry("panid"), CmdEntry("provisioningurl"),
679*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("sessionid"), CmdEntry("start"),   CmdEntry("state"), CmdEntry("stop"),
680*cfb92d14SAndroid Build Coastguard Worker     };
681*cfb92d14SAndroid Build Coastguard Worker 
682*cfb92d14SAndroid Build Coastguard Worker #undef CmdEntry
683*cfb92d14SAndroid Build Coastguard Worker 
684*cfb92d14SAndroid Build Coastguard Worker     static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
685*cfb92d14SAndroid Build Coastguard Worker 
686*cfb92d14SAndroid Build Coastguard Worker     otError        error = OT_ERROR_INVALID_COMMAND;
687*cfb92d14SAndroid Build Coastguard Worker     const Command *command;
688*cfb92d14SAndroid Build Coastguard Worker 
689*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
690*cfb92d14SAndroid Build Coastguard Worker     {
691*cfb92d14SAndroid Build Coastguard Worker         OutputCommandTable(kCommands);
692*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
693*cfb92d14SAndroid Build Coastguard Worker     }
694*cfb92d14SAndroid Build Coastguard Worker 
695*cfb92d14SAndroid Build Coastguard Worker     command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
696*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(command != nullptr);
697*cfb92d14SAndroid Build Coastguard Worker 
698*cfb92d14SAndroid Build Coastguard Worker     error = (this->*command->mHandler)(aArgs + 1);
699*cfb92d14SAndroid Build Coastguard Worker 
700*cfb92d14SAndroid Build Coastguard Worker exit:
701*cfb92d14SAndroid Build Coastguard Worker     return error;
702*cfb92d14SAndroid Build Coastguard Worker }
703*cfb92d14SAndroid Build Coastguard Worker 
HandleEnergyReport(uint32_t aChannelMask,const uint8_t * aEnergyList,uint8_t aEnergyListLength,void * aContext)704*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandleEnergyReport(uint32_t       aChannelMask,
705*cfb92d14SAndroid Build Coastguard Worker                                       const uint8_t *aEnergyList,
706*cfb92d14SAndroid Build Coastguard Worker                                       uint8_t        aEnergyListLength,
707*cfb92d14SAndroid Build Coastguard Worker                                       void          *aContext)
708*cfb92d14SAndroid Build Coastguard Worker {
709*cfb92d14SAndroid Build Coastguard Worker     static_cast<Commissioner *>(aContext)->HandleEnergyReport(aChannelMask, aEnergyList, aEnergyListLength);
710*cfb92d14SAndroid Build Coastguard Worker }
711*cfb92d14SAndroid Build Coastguard Worker 
HandleEnergyReport(uint32_t aChannelMask,const uint8_t * aEnergyList,uint8_t aEnergyListLength)712*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandleEnergyReport(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength)
713*cfb92d14SAndroid Build Coastguard Worker {
714*cfb92d14SAndroid Build Coastguard Worker     OutputFormat("Energy: %08lx ", ToUlong(aChannelMask));
715*cfb92d14SAndroid Build Coastguard Worker 
716*cfb92d14SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < aEnergyListLength; i++)
717*cfb92d14SAndroid Build Coastguard Worker     {
718*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("%d ", static_cast<int8_t>(aEnergyList[i]));
719*cfb92d14SAndroid Build Coastguard Worker     }
720*cfb92d14SAndroid Build Coastguard Worker 
721*cfb92d14SAndroid Build Coastguard Worker     OutputNewLine();
722*cfb92d14SAndroid Build Coastguard Worker }
723*cfb92d14SAndroid Build Coastguard Worker 
HandlePanIdConflict(uint16_t aPanId,uint32_t aChannelMask,void * aContext)724*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandlePanIdConflict(uint16_t aPanId, uint32_t aChannelMask, void *aContext)
725*cfb92d14SAndroid Build Coastguard Worker {
726*cfb92d14SAndroid Build Coastguard Worker     static_cast<Commissioner *>(aContext)->HandlePanIdConflict(aPanId, aChannelMask);
727*cfb92d14SAndroid Build Coastguard Worker }
728*cfb92d14SAndroid Build Coastguard Worker 
HandlePanIdConflict(uint16_t aPanId,uint32_t aChannelMask)729*cfb92d14SAndroid Build Coastguard Worker void Commissioner::HandlePanIdConflict(uint16_t aPanId, uint32_t aChannelMask)
730*cfb92d14SAndroid Build Coastguard Worker {
731*cfb92d14SAndroid Build Coastguard Worker     OutputLine("Conflict: %04x, %08lx", aPanId, ToUlong(aChannelMask));
732*cfb92d14SAndroid Build Coastguard Worker }
733*cfb92d14SAndroid Build Coastguard Worker 
734*cfb92d14SAndroid Build Coastguard Worker } // namespace Cli
735*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
736*cfb92d14SAndroid Build Coastguard Worker 
737*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
738