1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker * Copyright (c) 2024, The OpenThread Authors.
3*4a64e381SAndroid Build Coastguard Worker * All rights reserved.
4*4a64e381SAndroid Build Coastguard Worker *
5*4a64e381SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*4a64e381SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
7*4a64e381SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
8*4a64e381SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
9*4a64e381SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
10*4a64e381SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
11*4a64e381SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
12*4a64e381SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the
13*4a64e381SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products
14*4a64e381SAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
15*4a64e381SAndroid Build Coastguard Worker *
16*4a64e381SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*4a64e381SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*4a64e381SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*4a64e381SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*4a64e381SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*4a64e381SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*4a64e381SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*4a64e381SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*4a64e381SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*4a64e381SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*4a64e381SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
27*4a64e381SAndroid Build Coastguard Worker */
28*4a64e381SAndroid Build Coastguard Worker
29*4a64e381SAndroid Build Coastguard Worker #define OTBR_LOG_TAG "NCP_HOST"
30*4a64e381SAndroid Build Coastguard Worker
31*4a64e381SAndroid Build Coastguard Worker #include "ncp_host.hpp"
32*4a64e381SAndroid Build Coastguard Worker
33*4a64e381SAndroid Build Coastguard Worker #include <memory>
34*4a64e381SAndroid Build Coastguard Worker
35*4a64e381SAndroid Build Coastguard Worker #include <openthread/error.h>
36*4a64e381SAndroid Build Coastguard Worker #include <openthread/thread.h>
37*4a64e381SAndroid Build Coastguard Worker
38*4a64e381SAndroid Build Coastguard Worker #include <openthread/openthread-system.h>
39*4a64e381SAndroid Build Coastguard Worker
40*4a64e381SAndroid Build Coastguard Worker #include "lib/spinel/spinel_driver.hpp"
41*4a64e381SAndroid Build Coastguard Worker
42*4a64e381SAndroid Build Coastguard Worker #include "ncp/async_task.hpp"
43*4a64e381SAndroid Build Coastguard Worker
44*4a64e381SAndroid Build Coastguard Worker namespace otbr {
45*4a64e381SAndroid Build Coastguard Worker namespace Ncp {
46*4a64e381SAndroid Build Coastguard Worker
47*4a64e381SAndroid Build Coastguard Worker // =============================== NcpNetworkProperties ===============================
48*4a64e381SAndroid Build Coastguard Worker
NcpNetworkProperties(void)49*4a64e381SAndroid Build Coastguard Worker NcpNetworkProperties::NcpNetworkProperties(void)
50*4a64e381SAndroid Build Coastguard Worker : mDeviceRole(OT_DEVICE_ROLE_DISABLED)
51*4a64e381SAndroid Build Coastguard Worker {
52*4a64e381SAndroid Build Coastguard Worker memset(&mDatasetActiveTlvs, 0, sizeof(mDatasetActiveTlvs));
53*4a64e381SAndroid Build Coastguard Worker }
54*4a64e381SAndroid Build Coastguard Worker
GetDeviceRole(void) const55*4a64e381SAndroid Build Coastguard Worker otDeviceRole NcpNetworkProperties::GetDeviceRole(void) const
56*4a64e381SAndroid Build Coastguard Worker {
57*4a64e381SAndroid Build Coastguard Worker return mDeviceRole;
58*4a64e381SAndroid Build Coastguard Worker }
59*4a64e381SAndroid Build Coastguard Worker
SetDeviceRole(otDeviceRole aRole)60*4a64e381SAndroid Build Coastguard Worker void NcpNetworkProperties::SetDeviceRole(otDeviceRole aRole)
61*4a64e381SAndroid Build Coastguard Worker {
62*4a64e381SAndroid Build Coastguard Worker mDeviceRole = aRole;
63*4a64e381SAndroid Build Coastguard Worker }
64*4a64e381SAndroid Build Coastguard Worker
Ip6IsEnabled(void) const65*4a64e381SAndroid Build Coastguard Worker bool NcpNetworkProperties::Ip6IsEnabled(void) const
66*4a64e381SAndroid Build Coastguard Worker {
67*4a64e381SAndroid Build Coastguard Worker // TODO: Implement the method under NCP mode.
68*4a64e381SAndroid Build Coastguard Worker return false;
69*4a64e381SAndroid Build Coastguard Worker }
70*4a64e381SAndroid Build Coastguard Worker
GetPartitionId(void) const71*4a64e381SAndroid Build Coastguard Worker uint32_t NcpNetworkProperties::GetPartitionId(void) const
72*4a64e381SAndroid Build Coastguard Worker {
73*4a64e381SAndroid Build Coastguard Worker // TODO: Implement the method under NCP mode.
74*4a64e381SAndroid Build Coastguard Worker return 0;
75*4a64e381SAndroid Build Coastguard Worker }
76*4a64e381SAndroid Build Coastguard Worker
SetDatasetActiveTlvs(const otOperationalDatasetTlvs & aActiveOpDatasetTlvs)77*4a64e381SAndroid Build Coastguard Worker void NcpNetworkProperties::SetDatasetActiveTlvs(const otOperationalDatasetTlvs &aActiveOpDatasetTlvs)
78*4a64e381SAndroid Build Coastguard Worker {
79*4a64e381SAndroid Build Coastguard Worker mDatasetActiveTlvs.mLength = aActiveOpDatasetTlvs.mLength;
80*4a64e381SAndroid Build Coastguard Worker memcpy(mDatasetActiveTlvs.mTlvs, aActiveOpDatasetTlvs.mTlvs, aActiveOpDatasetTlvs.mLength);
81*4a64e381SAndroid Build Coastguard Worker }
82*4a64e381SAndroid Build Coastguard Worker
GetDatasetActiveTlvs(otOperationalDatasetTlvs & aDatasetTlvs) const83*4a64e381SAndroid Build Coastguard Worker void NcpNetworkProperties::GetDatasetActiveTlvs(otOperationalDatasetTlvs &aDatasetTlvs) const
84*4a64e381SAndroid Build Coastguard Worker {
85*4a64e381SAndroid Build Coastguard Worker aDatasetTlvs.mLength = mDatasetActiveTlvs.mLength;
86*4a64e381SAndroid Build Coastguard Worker memcpy(aDatasetTlvs.mTlvs, mDatasetActiveTlvs.mTlvs, mDatasetActiveTlvs.mLength);
87*4a64e381SAndroid Build Coastguard Worker }
88*4a64e381SAndroid Build Coastguard Worker
GetDatasetPendingTlvs(otOperationalDatasetTlvs & aDatasetTlvs) const89*4a64e381SAndroid Build Coastguard Worker void NcpNetworkProperties::GetDatasetPendingTlvs(otOperationalDatasetTlvs &aDatasetTlvs) const
90*4a64e381SAndroid Build Coastguard Worker {
91*4a64e381SAndroid Build Coastguard Worker // TODO: Implement the method under NCP mode.
92*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aDatasetTlvs);
93*4a64e381SAndroid Build Coastguard Worker }
94*4a64e381SAndroid Build Coastguard Worker
95*4a64e381SAndroid Build Coastguard Worker // ===================================== NcpHost ======================================
96*4a64e381SAndroid Build Coastguard Worker
NcpHost(const char * aInterfaceName,bool aDryRun)97*4a64e381SAndroid Build Coastguard Worker NcpHost::NcpHost(const char *aInterfaceName, bool aDryRun)
98*4a64e381SAndroid Build Coastguard Worker : mSpinelDriver(*static_cast<ot::Spinel::SpinelDriver *>(otSysGetSpinelDriver()))
99*4a64e381SAndroid Build Coastguard Worker , mNetif()
100*4a64e381SAndroid Build Coastguard Worker {
101*4a64e381SAndroid Build Coastguard Worker memset(&mConfig, 0, sizeof(mConfig));
102*4a64e381SAndroid Build Coastguard Worker mConfig.mInterfaceName = aInterfaceName;
103*4a64e381SAndroid Build Coastguard Worker mConfig.mDryRun = aDryRun;
104*4a64e381SAndroid Build Coastguard Worker mConfig.mSpeedUpFactor = 1;
105*4a64e381SAndroid Build Coastguard Worker }
106*4a64e381SAndroid Build Coastguard Worker
GetCoprocessorVersion(void)107*4a64e381SAndroid Build Coastguard Worker const char *NcpHost::GetCoprocessorVersion(void)
108*4a64e381SAndroid Build Coastguard Worker {
109*4a64e381SAndroid Build Coastguard Worker return mSpinelDriver.GetVersion();
110*4a64e381SAndroid Build Coastguard Worker }
111*4a64e381SAndroid Build Coastguard Worker
Init(void)112*4a64e381SAndroid Build Coastguard Worker void NcpHost::Init(void)
113*4a64e381SAndroid Build Coastguard Worker {
114*4a64e381SAndroid Build Coastguard Worker otSysInit(&mConfig);
115*4a64e381SAndroid Build Coastguard Worker mNcpSpinel.Init(mSpinelDriver, *this);
116*4a64e381SAndroid Build Coastguard Worker mNetif.Init(mConfig.mInterfaceName,
117*4a64e381SAndroid Build Coastguard Worker [this](const uint8_t *aData, uint16_t aLength) { return mNcpSpinel.Ip6Send(aData, aLength); });
118*4a64e381SAndroid Build Coastguard Worker
119*4a64e381SAndroid Build Coastguard Worker mNcpSpinel.Ip6SetAddressCallback(
120*4a64e381SAndroid Build Coastguard Worker [this](const std::vector<Ip6AddressInfo> &aAddrInfos) { mNetif.UpdateIp6UnicastAddresses(aAddrInfos); });
121*4a64e381SAndroid Build Coastguard Worker mNcpSpinel.Ip6SetAddressMulticastCallback(
122*4a64e381SAndroid Build Coastguard Worker [this](const std::vector<Ip6Address> &aAddrs) { mNetif.UpdateIp6MulticastAddresses(aAddrs); });
123*4a64e381SAndroid Build Coastguard Worker mNcpSpinel.NetifSetStateChangedCallback([this](bool aState) { mNetif.SetNetifState(aState); });
124*4a64e381SAndroid Build Coastguard Worker }
125*4a64e381SAndroid Build Coastguard Worker
Deinit(void)126*4a64e381SAndroid Build Coastguard Worker void NcpHost::Deinit(void)
127*4a64e381SAndroid Build Coastguard Worker {
128*4a64e381SAndroid Build Coastguard Worker mNcpSpinel.Deinit();
129*4a64e381SAndroid Build Coastguard Worker mNetif.Deinit();
130*4a64e381SAndroid Build Coastguard Worker otSysDeinit();
131*4a64e381SAndroid Build Coastguard Worker }
132*4a64e381SAndroid Build Coastguard Worker
Join(const otOperationalDatasetTlvs & aActiveOpDatasetTlvs,const AsyncResultReceiver & aReceiver)133*4a64e381SAndroid Build Coastguard Worker void NcpHost::Join(const otOperationalDatasetTlvs &aActiveOpDatasetTlvs, const AsyncResultReceiver &aReceiver)
134*4a64e381SAndroid Build Coastguard Worker {
135*4a64e381SAndroid Build Coastguard Worker AsyncTaskPtr task;
136*4a64e381SAndroid Build Coastguard Worker auto errorHandler = [aReceiver](otError aError, const std::string &aErrorInfo) { aReceiver(aError, aErrorInfo); };
137*4a64e381SAndroid Build Coastguard Worker
138*4a64e381SAndroid Build Coastguard Worker task = std::make_shared<AsyncTask>(errorHandler);
139*4a64e381SAndroid Build Coastguard Worker task->First([this, aActiveOpDatasetTlvs](AsyncTaskPtr aNext) {
140*4a64e381SAndroid Build Coastguard Worker mNcpSpinel.DatasetSetActiveTlvs(aActiveOpDatasetTlvs, std::move(aNext));
141*4a64e381SAndroid Build Coastguard Worker })
142*4a64e381SAndroid Build Coastguard Worker ->Then([this](AsyncTaskPtr aNext) { mNcpSpinel.Ip6SetEnabled(true, std::move(aNext)); })
143*4a64e381SAndroid Build Coastguard Worker ->Then([this](AsyncTaskPtr aNext) { mNcpSpinel.ThreadSetEnabled(true, std::move(aNext)); });
144*4a64e381SAndroid Build Coastguard Worker task->Run();
145*4a64e381SAndroid Build Coastguard Worker }
146*4a64e381SAndroid Build Coastguard Worker
Leave(const AsyncResultReceiver & aReceiver)147*4a64e381SAndroid Build Coastguard Worker void NcpHost::Leave(const AsyncResultReceiver &aReceiver)
148*4a64e381SAndroid Build Coastguard Worker {
149*4a64e381SAndroid Build Coastguard Worker AsyncTaskPtr task;
150*4a64e381SAndroid Build Coastguard Worker auto errorHandler = [aReceiver](otError aError, const std::string &aErrorInfo) { aReceiver(aError, aErrorInfo); };
151*4a64e381SAndroid Build Coastguard Worker
152*4a64e381SAndroid Build Coastguard Worker task = std::make_shared<AsyncTask>(errorHandler);
153*4a64e381SAndroid Build Coastguard Worker task->First([this](AsyncTaskPtr aNext) { mNcpSpinel.ThreadDetachGracefully(std::move(aNext)); })
154*4a64e381SAndroid Build Coastguard Worker ->Then([this](AsyncTaskPtr aNext) { mNcpSpinel.ThreadErasePersistentInfo(std::move(aNext)); });
155*4a64e381SAndroid Build Coastguard Worker task->Run();
156*4a64e381SAndroid Build Coastguard Worker }
157*4a64e381SAndroid Build Coastguard Worker
ScheduleMigration(const otOperationalDatasetTlvs & aPendingOpDatasetTlvs,const AsyncResultReceiver aReceiver)158*4a64e381SAndroid Build Coastguard Worker void NcpHost::ScheduleMigration(const otOperationalDatasetTlvs &aPendingOpDatasetTlvs,
159*4a64e381SAndroid Build Coastguard Worker const AsyncResultReceiver aReceiver)
160*4a64e381SAndroid Build Coastguard Worker {
161*4a64e381SAndroid Build Coastguard Worker otDeviceRole role = GetDeviceRole();
162*4a64e381SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
163*4a64e381SAndroid Build Coastguard Worker auto errorHandler = [aReceiver](otError aError, const std::string &aErrorInfo) { aReceiver(aError, aErrorInfo); };
164*4a64e381SAndroid Build Coastguard Worker
165*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(role != OT_DEVICE_ROLE_DISABLED && role != OT_DEVICE_ROLE_DETACHED, error = OT_ERROR_INVALID_STATE);
166*4a64e381SAndroid Build Coastguard Worker
167*4a64e381SAndroid Build Coastguard Worker mNcpSpinel.DatasetMgmtSetPending(std::make_shared<otOperationalDatasetTlvs>(aPendingOpDatasetTlvs),
168*4a64e381SAndroid Build Coastguard Worker std::make_shared<AsyncTask>(errorHandler));
169*4a64e381SAndroid Build Coastguard Worker
170*4a64e381SAndroid Build Coastguard Worker exit:
171*4a64e381SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
172*4a64e381SAndroid Build Coastguard Worker {
173*4a64e381SAndroid Build Coastguard Worker mTaskRunner.Post(
174*4a64e381SAndroid Build Coastguard Worker [aReceiver, error](void) { aReceiver(error, "Cannot schedule migration when this device is detached"); });
175*4a64e381SAndroid Build Coastguard Worker }
176*4a64e381SAndroid Build Coastguard Worker }
177*4a64e381SAndroid Build Coastguard Worker
SetThreadEnabled(bool aEnabled,const AsyncResultReceiver aReceiver)178*4a64e381SAndroid Build Coastguard Worker void NcpHost::SetThreadEnabled(bool aEnabled, const AsyncResultReceiver aReceiver)
179*4a64e381SAndroid Build Coastguard Worker {
180*4a64e381SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aEnabled);
181*4a64e381SAndroid Build Coastguard Worker
182*4a64e381SAndroid Build Coastguard Worker // TODO: Implement SetThreadEnabled under NCP mode.
183*4a64e381SAndroid Build Coastguard Worker mTaskRunner.Post([aReceiver](void) { aReceiver(OT_ERROR_NOT_IMPLEMENTED, "Not implemented!"); });
184*4a64e381SAndroid Build Coastguard Worker }
185*4a64e381SAndroid Build Coastguard Worker
SetCountryCode(const std::string & aCountryCode,const AsyncResultReceiver & aReceiver)186*4a64e381SAndroid Build Coastguard Worker void NcpHost::SetCountryCode(const std::string &aCountryCode, const AsyncResultReceiver &aReceiver)
187*4a64e381SAndroid Build Coastguard Worker {
188*4a64e381SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aCountryCode);
189*4a64e381SAndroid Build Coastguard Worker
190*4a64e381SAndroid Build Coastguard Worker // TODO: Implement SetCountryCode under NCP mode.
191*4a64e381SAndroid Build Coastguard Worker mTaskRunner.Post([aReceiver](void) { aReceiver(OT_ERROR_NOT_IMPLEMENTED, "Not implemented!"); });
192*4a64e381SAndroid Build Coastguard Worker }
193*4a64e381SAndroid Build Coastguard Worker
GetChannelMasks(const ChannelMasksReceiver & aReceiver,const AsyncResultReceiver & aErrReceiver)194*4a64e381SAndroid Build Coastguard Worker void NcpHost::GetChannelMasks(const ChannelMasksReceiver &aReceiver, const AsyncResultReceiver &aErrReceiver)
195*4a64e381SAndroid Build Coastguard Worker {
196*4a64e381SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aReceiver);
197*4a64e381SAndroid Build Coastguard Worker
198*4a64e381SAndroid Build Coastguard Worker // TODO: Implement GetChannelMasks under NCP mode.
199*4a64e381SAndroid Build Coastguard Worker mTaskRunner.Post([aErrReceiver](void) { aErrReceiver(OT_ERROR_NOT_IMPLEMENTED, "Not implemented!"); });
200*4a64e381SAndroid Build Coastguard Worker }
201*4a64e381SAndroid Build Coastguard Worker
SetChannelMaxPowers(const std::vector<ChannelMaxPower> & aChannelMaxPowers,const AsyncResultReceiver & aReceiver)202*4a64e381SAndroid Build Coastguard Worker void NcpHost::SetChannelMaxPowers(const std::vector<ChannelMaxPower> &aChannelMaxPowers,
203*4a64e381SAndroid Build Coastguard Worker const AsyncResultReceiver &aReceiver)
204*4a64e381SAndroid Build Coastguard Worker {
205*4a64e381SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aChannelMaxPowers);
206*4a64e381SAndroid Build Coastguard Worker
207*4a64e381SAndroid Build Coastguard Worker // TODO: Implement SetChannelMaxPowers under NCP mode.
208*4a64e381SAndroid Build Coastguard Worker mTaskRunner.Post([aReceiver](void) { aReceiver(OT_ERROR_NOT_IMPLEMENTED, "Not implemented!"); });
209*4a64e381SAndroid Build Coastguard Worker }
210*4a64e381SAndroid Build Coastguard Worker
AddThreadStateChangedCallback(ThreadStateChangedCallback aCallback)211*4a64e381SAndroid Build Coastguard Worker void NcpHost::AddThreadStateChangedCallback(ThreadStateChangedCallback aCallback)
212*4a64e381SAndroid Build Coastguard Worker {
213*4a64e381SAndroid Build Coastguard Worker // TODO: Implement AddThreadStateChangedCallback under NCP mode.
214*4a64e381SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aCallback);
215*4a64e381SAndroid Build Coastguard Worker }
216*4a64e381SAndroid Build Coastguard Worker
Process(const MainloopContext & aMainloop)217*4a64e381SAndroid Build Coastguard Worker void NcpHost::Process(const MainloopContext &aMainloop)
218*4a64e381SAndroid Build Coastguard Worker {
219*4a64e381SAndroid Build Coastguard Worker mSpinelDriver.Process(&aMainloop);
220*4a64e381SAndroid Build Coastguard Worker }
221*4a64e381SAndroid Build Coastguard Worker
Update(MainloopContext & aMainloop)222*4a64e381SAndroid Build Coastguard Worker void NcpHost::Update(MainloopContext &aMainloop)
223*4a64e381SAndroid Build Coastguard Worker {
224*4a64e381SAndroid Build Coastguard Worker mSpinelDriver.GetSpinelInterface()->UpdateFdSet(&aMainloop);
225*4a64e381SAndroid Build Coastguard Worker
226*4a64e381SAndroid Build Coastguard Worker if (mSpinelDriver.HasPendingFrame())
227*4a64e381SAndroid Build Coastguard Worker {
228*4a64e381SAndroid Build Coastguard Worker aMainloop.mTimeout.tv_sec = 0;
229*4a64e381SAndroid Build Coastguard Worker aMainloop.mTimeout.tv_usec = 0;
230*4a64e381SAndroid Build Coastguard Worker }
231*4a64e381SAndroid Build Coastguard Worker }
232*4a64e381SAndroid Build Coastguard Worker
233*4a64e381SAndroid Build Coastguard Worker } // namespace Ncp
234*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
235