• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "thread_chip.hpp"
18 
19 #include <android-base/logging.h>
20 #include <android/binder_auto_utils.h>
21 #include <android/binder_ibinder.h>
22 #include <android/binder_manager.h>
23 #include <android/binder_process.h>
24 #include <utils/Log.h>
25 
26 #include "hdlc_interface.hpp"
27 #include "socket_interface.hpp"
28 #include "spi_interface.hpp"
29 
30 namespace aidl {
31 namespace android {
32 namespace hardware {
33 namespace threadnetwork {
34 
ThreadChip(const char * url)35 ThreadChip::ThreadChip(const char* url) : mUrl(url), mRxFrameBuffer(), mCallback(nullptr) {
36     const char* interfaceName;
37 
38     interfaceName = mUrl.GetProtocol();
39     CHECK_NE(interfaceName, nullptr);
40 
41     if (ot::Posix::SpiInterface::IsInterfaceNameMatch(interfaceName)) {
42         mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(mUrl);
43     } else if (ot::Posix::HdlcInterface::IsInterfaceNameMatch(interfaceName)) {
44         mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(mUrl);
45     } else if (SocketInterface::IsInterfaceNameMatch(interfaceName)) {
46         mSpinelInterface = std::make_shared<SocketInterface>(mUrl);
47     } else {
48         ALOGE("The interface \"%s\" is not supported", interfaceName);
49         exit(EXIT_FAILURE);
50     }
51 
52     CHECK_NE(mSpinelInterface, nullptr);
53 
54     mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
55             AIBinder_DeathRecipient_new(ThreadChip::onBinderDiedJump));
56     AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinkedJump);
57 }
58 
onBinderDiedJump(void * context)59 void ThreadChip::onBinderDiedJump(void* context) {
60     reinterpret_cast<ThreadChip*>(context)->onBinderDied();
61 }
62 
onBinderDied(void)63 void ThreadChip::onBinderDied(void) {
64     ALOGW("Thread Network HAL client is dead");
65 }
66 
onBinderUnlinkedJump(void * context)67 void ThreadChip::onBinderUnlinkedJump(void* context) {
68     reinterpret_cast<ThreadChip*>(context)->onBinderUnlinked();
69 }
70 
onBinderUnlinked(void)71 void ThreadChip::onBinderUnlinked(void) {
72     ALOGW("ThreadChip binder is unlinked");
73     deinitChip();
74 }
75 
handleReceivedFrameJump(void * context)76 void ThreadChip::handleReceivedFrameJump(void* context) {
77     static_cast<ThreadChip*>(context)->handleReceivedFrame();
78 }
79 
handleReceivedFrame(void)80 void ThreadChip::handleReceivedFrame(void) {
81     if (mCallback != nullptr) {
82         mCallback->onReceiveSpinelFrame(std::vector<uint8_t>(
83                 mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetFrame() + mRxFrameBuffer.GetLength()));
84     }
85 
86     if (mVendorCallback != nullptr) {
87         mVendorCallback->onReceiveSpinelFrame(std::vector<uint8_t>(
88                 mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetFrame() + mRxFrameBuffer.GetLength()));
89     }
90 
91     mRxFrameBuffer.DiscardFrame();
92 }
93 
open(const std::shared_ptr<IThreadChipCallback> & in_callback)94 ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>& in_callback) {
95     ndk::ScopedAStatus status = initChip(in_callback);
96 
97     if (status.isOk()) {
98         AIBinder_linkToDeath(in_callback->asBinder().get(), mDeathRecipient.get(), this);
99         ALOGI("Open IThreadChip successfully");
100     } else {
101         ALOGW("Failed to open IThreadChip: %s", status.getDescription().c_str());
102     }
103 
104     return status;
105 }
106 
initChip(const std::shared_ptr<IThreadChipCallback> & in_callback)107 ndk::ScopedAStatus ThreadChip::initChip(const std::shared_ptr<IThreadChipCallback>& in_callback) {
108     if (in_callback == nullptr) {
109         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
110     } else if (mCallback == nullptr) {
111         if (mSpinelInterface->Init(handleReceivedFrameJump, this, mRxFrameBuffer) !=
112             OT_ERROR_NONE) {
113             return errorStatus(ERROR_FAILED, "Failed to initialize the interface");
114         }
115 
116         mCallback = in_callback;
117         ot::Posix::Mainloop::Manager::Get().Add(*this);
118         return ndk::ScopedAStatus::ok();
119     } else {
120         return errorStatus(ERROR_BUSY, "Interface has been opened");
121     }
122 }
123 
close()124 ndk::ScopedAStatus ThreadChip::close() {
125     ndk::ScopedAStatus status;
126     std::shared_ptr<IThreadChipCallback> callback = mCallback;
127 
128     status = deinitChip();
129     if (status.isOk()) {
130         if (callback != nullptr) {
131             AIBinder_unlinkToDeath(callback->asBinder().get(), mDeathRecipient.get(), this);
132         }
133 
134         ALOGI("Close IThreadChip successfully");
135     } else {
136         ALOGW("Failed to close IThreadChip: %s", status.getDescription().c_str());
137     }
138 
139     return status;
140 }
141 
deinitChip()142 ndk::ScopedAStatus ThreadChip::deinitChip() {
143     if (mCallback != nullptr) {
144         mSpinelInterface->Deinit();
145         ot::Posix::Mainloop::Manager::Get().Remove(*this);
146         mCallback = nullptr;
147         return ndk::ScopedAStatus::ok();
148     }
149 
150     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
151 }
152 
sendSpinelFrame(const std::vector<uint8_t> & in_frame)153 ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_frame) {
154     ndk::ScopedAStatus status;
155     otError error;
156 
157     if (mCallback == nullptr) {
158         status = errorStatus(ERROR_FAILED, "The interface is not open");
159     } else {
160         error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
161                                             in_frame.size());
162         if (error == OT_ERROR_NONE) {
163             status = ndk::ScopedAStatus::ok();
164         } else if (error == OT_ERROR_NO_BUFS) {
165             status = errorStatus(ERROR_NO_BUFS, "Insufficient buffer space to send");
166         } else if (error == OT_ERROR_BUSY) {
167             status = errorStatus(ERROR_BUSY, "The interface is busy");
168         } else {
169             status = errorStatus(ERROR_FAILED, "Failed to send the spinel frame");
170         }
171     }
172 
173     if (!status.isOk()) {
174         ALOGW("Send spinel frame failed, error: %s", status.getDescription().c_str());
175     }
176 
177     return status;
178 }
179 
hardwareReset()180 ndk::ScopedAStatus ThreadChip::hardwareReset() {
181     if (mSpinelInterface->HardwareReset() == OT_ERROR_NOT_IMPLEMENTED) {
182         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
183     }
184 
185     ALOGI("reset()");
186     return ndk::ScopedAStatus::ok();
187 }
188 
Update(otSysMainloopContext & context)189 void ThreadChip::Update(otSysMainloopContext& context) {
190     if (mCallback != nullptr) {
191         mSpinelInterface->UpdateFdSet(&context);
192     }
193 }
194 
Process(const otSysMainloopContext & context)195 void ThreadChip::Process(const otSysMainloopContext& context) {
196     if (mCallback != nullptr) {
197         mSpinelInterface->Process(&context);
198     }
199 }
200 
setVendorCallback(const std::shared_ptr<IThreadChipCallback> & vendorCallback)201 void ThreadChip::setVendorCallback(const std::shared_ptr<IThreadChipCallback>& vendorCallback) {
202     mVendorCallback = vendorCallback;
203 }
204 
errorStatus(int32_t error,const char * message)205 ndk::ScopedAStatus ThreadChip::errorStatus(int32_t error, const char* message) {
206     return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(error, message));
207 }
208 }  // namespace threadnetwork
209 }  // namespace hardware
210 }  // namespace android
211 }  // namespace aidl
212