blob: 3d38cb841bb5436058bae0affb7809231ebfe1e5 [file] [log] [blame]
Zhanglong Xia24e52742023-06-14 05:25:55 +00001/*
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>
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +080020#include <android/binder_auto_utils.h>
21#include <android/binder_ibinder.h>
Zhanglong Xia24e52742023-06-14 05:25:55 +000022#include <android/binder_manager.h>
23#include <android/binder_process.h>
Zhanglong Xia5c027012023-06-15 10:15:59 +080024#include <utils/Log.h>
Zhanglong Xia24e52742023-06-14 05:25:55 +000025
Zhanglong Xia7ae6d6f2023-07-03 10:52:45 +080026#include "hdlc_interface.hpp"
27#include "spi_interface.hpp"
28
Zhanglong Xia24e52742023-06-14 05:25:55 +000029namespace aidl {
30namespace android {
31namespace hardware {
32namespace threadnetwork {
33
Zhanglong Xia7ae6d6f2023-07-03 10:52:45 +080034ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) {
35 static const char kHdlcProtocol[] = "spinel+hdlc";
36 static const char kSpiProtocol[] = "spinel+spi";
37 const char* protocol;
38
Zhanglong Xia24e52742023-06-14 05:25:55 +000039 CHECK_EQ(mUrl.Init(url), 0);
Zhanglong Xia7ae6d6f2023-07-03 10:52:45 +080040
41 protocol = mUrl.GetProtocol();
42 CHECK_NE(protocol, nullptr);
43
44 if (memcmp(protocol, kSpiProtocol, strlen(kSpiProtocol)) == 0) {
45 mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(handleReceivedFrameJump, this,
46 mRxFrameBuffer);
47 } else if (memcmp(protocol, kHdlcProtocol, strlen(kHdlcProtocol)) == 0) {
48 mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this,
49 mRxFrameBuffer);
50 } else {
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +080051 ALOGE("The protocol \"%s\" is not supported", protocol);
52 exit(EXIT_FAILURE);
Zhanglong Xia7ae6d6f2023-07-03 10:52:45 +080053 }
54
55 CHECK_NE(mSpinelInterface, nullptr);
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +080056
57 mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
58 AIBinder_DeathRecipient_new(ThreadChip::onBinderDiedJump));
59 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinkedJump);
Zhanglong Xia24e52742023-06-14 05:25:55 +000060}
61
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +080062ThreadChip::~ThreadChip() {
63 AIBinder_DeathRecipient_delete(mDeathRecipient.get());
Zhanglong Xia24e52742023-06-14 05:25:55 +000064}
65
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +080066void ThreadChip::onBinderDiedJump(void* context) {
67 reinterpret_cast<ThreadChip*>(context)->onBinderDied();
68}
69
70void ThreadChip::onBinderDied(void) {
71 ALOGW("Thread Network HAL client is dead");
72}
73
74void ThreadChip::onBinderUnlinkedJump(void* context) {
75 reinterpret_cast<ThreadChip*>(context)->onBinderUnlinked();
76}
77
78void ThreadChip::onBinderUnlinked(void) {
79 ALOGW("ThreadChip binder is unlinked");
80 deinitChip();
Zhanglong Xia24e52742023-06-14 05:25:55 +000081}
82
Zhanglong Xia7ae6d6f2023-07-03 10:52:45 +080083void ThreadChip::handleReceivedFrameJump(void* context) {
Zhanglong Xia24e52742023-06-14 05:25:55 +000084 static_cast<ThreadChip*>(context)->handleReceivedFrame();
85}
86
87void ThreadChip::handleReceivedFrame(void) {
88 if (mCallback != nullptr) {
89 mCallback->onReceiveSpinelFrame(std::vector<uint8_t>(
90 mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetFrame() + mRxFrameBuffer.GetLength()));
91 }
92
93 mRxFrameBuffer.DiscardFrame();
94}
95
96ndk::ScopedAStatus ThreadChip::open(const std::shared_ptr<IThreadChipCallback>& in_callback) {
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +080097 ndk::ScopedAStatus status = initChip(in_callback);
Zhanglong Xia24e52742023-06-14 05:25:55 +000098
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +080099 if (status.isOk()) {
100 AIBinder_linkToDeath(in_callback->asBinder().get(), mDeathRecipient.get(), this);
101 ALOGI("Open IThreadChip successfully");
Zhanglong Xia5c027012023-06-15 10:15:59 +0800102 } else {
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800103 ALOGW("Failed to open IThreadChip: %s", status.getDescription().c_str());
Zhanglong Xia24e52742023-06-14 05:25:55 +0000104 }
105
106 return status;
107}
108
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800109ndk::ScopedAStatus ThreadChip::initChip(const std::shared_ptr<IThreadChipCallback>& in_callback) {
110 if (in_callback == nullptr) {
111 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
112 } else if (mCallback == nullptr) {
113 if (mSpinelInterface->Init(mUrl) != OT_ERROR_NONE) {
114 return errorStatus(ERROR_FAILED, "Failed to initialize the interface");
115 }
116
117 mCallback = in_callback;
118 ot::Posix::Mainloop::Manager::Get().Add(*this);
119 return ndk::ScopedAStatus::ok();
120 } else {
121 return errorStatus(ERROR_BUSY, "Interface has been opened");
122 }
123}
124
Zhanglong Xia24e52742023-06-14 05:25:55 +0000125ndk::ScopedAStatus ThreadChip::close() {
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800126 ndk::ScopedAStatus status;
127 std::shared_ptr<IThreadChipCallback> callback = mCallback;
Zhanglong Xia24e52742023-06-14 05:25:55 +0000128
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800129 status = deinitChip();
130 if (status.isOk()) {
131 if (callback != nullptr) {
132 AIBinder_unlinkToDeath(callback->asBinder().get(), mDeathRecipient.get(), this);
133 }
Zhanglong Xia24e52742023-06-14 05:25:55 +0000134
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800135 ALOGI("Close IThreadChip successfully");
136 } else {
137 ALOGW("Failed to close IThreadChip: %s", status.getDescription().c_str());
138 }
Zhanglong Xia24e52742023-06-14 05:25:55 +0000139
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800140 return status;
141}
142
143ndk::ScopedAStatus ThreadChip::deinitChip() {
144 if (mCallback != nullptr) {
145 mSpinelInterface->Deinit();
146 ot::Posix::Mainloop::Manager::Get().Remove(*this);
147 mCallback = nullptr;
148 return ndk::ScopedAStatus::ok();
149 }
150
151 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
Zhanglong Xia24e52742023-06-14 05:25:55 +0000152}
153
154ndk::ScopedAStatus ThreadChip::sendSpinelFrame(const std::vector<uint8_t>& in_frame) {
155 ndk::ScopedAStatus status;
156 otError error;
157
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800158 if (mCallback == nullptr) {
159 status = errorStatus(ERROR_FAILED, "The interface is not open");
Zhanglong Xia24e52742023-06-14 05:25:55 +0000160 } else {
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800161 error = mSpinelInterface->SendFrame(reinterpret_cast<const uint8_t*>(in_frame.data()),
162 in_frame.size());
163 if (error == OT_ERROR_NONE) {
164 status = ndk::ScopedAStatus::ok();
165 } else if (error == OT_ERROR_NO_BUFS) {
166 status = errorStatus(ERROR_NO_BUFS, "Insufficient buffer space to send");
167 } else if (error == OT_ERROR_BUSY) {
168 status = errorStatus(ERROR_BUSY, "The interface is busy");
169 } else {
170 status = errorStatus(ERROR_FAILED, "Failed to send the spinel frame");
171 }
Zhanglong Xia24e52742023-06-14 05:25:55 +0000172 }
173
Zhanglong Xia5c027012023-06-15 10:15:59 +0800174 if (!status.isOk()) {
Zhanglong Xia24e52742023-06-14 05:25:55 +0000175 ALOGW("Send spinel frame failed, error: %s", status.getDescription().c_str());
176 }
177
178 return status;
179}
180
Zhanglong Xiaa6165dc2023-07-06 18:09:22 +0800181ndk::ScopedAStatus ThreadChip::hardwareReset() {
182 if (mSpinelInterface->HardwareReset() == OT_ERROR_NOT_IMPLEMENTED) {
183 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
184 }
185
Zhanglong Xia24e52742023-06-14 05:25:55 +0000186 ALOGI("reset()");
187 return ndk::ScopedAStatus::ok();
188}
189
190void ThreadChip::Update(otSysMainloopContext& context) {
191 if (mCallback != nullptr) {
Zhanglong Xia7ae6d6f2023-07-03 10:52:45 +0800192 mSpinelInterface->UpdateFdSet(&context);
Zhanglong Xia24e52742023-06-14 05:25:55 +0000193 }
194}
195
196void ThreadChip::Process(const otSysMainloopContext& context) {
Zhanglong Xia24e52742023-06-14 05:25:55 +0000197 if (mCallback != nullptr) {
Zhanglong Xia7ae6d6f2023-07-03 10:52:45 +0800198 mSpinelInterface->Process(&context);
Zhanglong Xia24e52742023-06-14 05:25:55 +0000199 }
200}
201
202ndk::ScopedAStatus ThreadChip::errorStatus(int32_t error, const char* message) {
203 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(error, message));
204}
205} // namespace threadnetwork
206} // namespace hardware
207} // namespace android
208} // namespace aidl