blob: a247cb0f8fad6665276e33de2ca64c2200fd4c96 [file] [log] [blame]
Myles Watson6d5e7722022-09-30 06:22:43 -07001/*
2 * Copyright 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#define LOG_TAG "android.hardware.bluetooth.service.default"
18
19#include "BluetoothHci.h"
20
21#include <cutils/properties.h>
22#include <fcntl.h>
23#include <netdb.h>
24#include <netinet/in.h>
25#include <poll.h>
26#include <string.h>
27#include <sys/uio.h>
28#include <termios.h>
29
30#include "log/log.h"
31
32namespace {
33int SetTerminalRaw(int fd) {
34 termios terminal_settings;
35 int rval = tcgetattr(fd, &terminal_settings);
36 if (rval < 0) {
37 return rval;
38 }
39 cfmakeraw(&terminal_settings);
40 rval = tcsetattr(fd, TCSANOW, &terminal_settings);
41 return rval;
42}
43} // namespace
44
45using namespace ::android::hardware::bluetooth::hci;
46using namespace ::android::hardware::bluetooth::async;
Myles Watsonefa25d72022-10-03 16:27:32 -070047using aidl::android::hardware::bluetooth::Status;
Myles Watson6d5e7722022-09-30 06:22:43 -070048
49namespace aidl::android::hardware::bluetooth::impl {
50
51void OnDeath(void* cookie);
52
Henri Chataing1267ff22023-08-09 22:38:24 +000053std::optional<std::string> GetSystemProperty(const std::string& property) {
54 std::array<char, PROPERTY_VALUE_MAX> value_array{0};
55 auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
56 if (value_len <= 0) {
57 return std::nullopt;
58 }
59 return std::string(value_array.data(), value_len);
60}
61
62bool starts_with(const std::string& str, const std::string& prefix) {
63 return str.compare(0, prefix.length(), prefix) == 0;
64}
65
Myles Watson6d5e7722022-09-30 06:22:43 -070066class BluetoothDeathRecipient {
67 public:
68 BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
69
70 void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
71 mCb = cb;
72 clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
73 auto linkToDeathReturnStatus = AIBinder_linkToDeath(
74 mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
75 LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
76 "Unable to link to death recipient");
77 }
78
79 void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
80 LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
81 }
82
83 void serviceDied() {
84 if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
85 ALOGE("Bluetooth remote service has died");
86 } else {
87 ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
88 return;
89 }
Myles Watson65b47f52023-01-26 12:59:06 -080090 {
91 std::lock_guard<std::mutex> guard(mHasDiedMutex);
92 has_died_ = true;
93 }
Myles Watson6d5e7722022-09-30 06:22:43 -070094 mHci->close();
95 }
96 BluetoothHci* mHci;
97 std::shared_ptr<IBluetoothHciCallbacks> mCb;
98 AIBinder_DeathRecipient* clientDeathRecipient_;
Myles Watson65b47f52023-01-26 12:59:06 -080099 bool getHasDied() {
100 std::lock_guard<std::mutex> guard(mHasDiedMutex);
101 return has_died_;
102 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700103
104 private:
Myles Watson65b47f52023-01-26 12:59:06 -0800105 std::mutex mHasDiedMutex;
Myles Watson8678c752022-11-03 10:41:44 -0700106 bool has_died_{false};
Myles Watson6d5e7722022-09-30 06:22:43 -0700107};
108
109void OnDeath(void* cookie) {
110 auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
111 death_recipient->serviceDied();
112}
113
114BluetoothHci::BluetoothHci(const std::string& dev_path) {
115 char property_bytes[PROPERTY_VALUE_MAX];
116 property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
117 mDevPath = std::string(property_bytes);
118 mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
119}
120
Myles Watsonefa25d72022-10-03 16:27:32 -0700121int BluetoothHci::getFdFromDevPath() {
122 int fd = open(mDevPath.c_str(), O_RDWR);
123 if (fd < 0) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700124 ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
125 strerror(errno));
Myles Watsonefa25d72022-10-03 16:27:32 -0700126 return fd;
Myles Watson6d5e7722022-09-30 06:22:43 -0700127 }
yanggang.yangeb744bc2023-04-21 11:05:42 +0800128 if (int ret = SetTerminalRaw(fd) < 0) {
129 ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
Myles Watson6d5e7722022-09-30 06:22:43 -0700130 strerror(errno));
Myles Watson6d5e7722022-09-30 06:22:43 -0700131 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700132 return fd;
133}
134
Myles Watson65b47f52023-01-26 12:59:06 -0800135void BluetoothHci::reset() {
136 // Send a reset command and wait until the command complete comes back.
137
Myles Watson47c02822023-08-28 11:53:31 -0700138 std::vector<uint8_t> reset = {0x03, 0x0c, 0x00};
Myles Watson65b47f52023-01-26 12:59:06 -0800139
140 auto resetPromise = std::make_shared<std::promise<void>>();
141 auto resetFuture = resetPromise->get_future();
142
143 mH4 = std::make_shared<H4Protocol>(
144 mFd,
145 [](const std::vector<uint8_t>& raw_command) {
146 ALOGI("Discarding %d bytes with command type",
147 static_cast<int>(raw_command.size()));
148 },
149 [](const std::vector<uint8_t>& raw_acl) {
150 ALOGI("Discarding %d bytes with acl type",
151 static_cast<int>(raw_acl.size()));
152 },
153 [](const std::vector<uint8_t>& raw_sco) {
154 ALOGI("Discarding %d bytes with sco type",
155 static_cast<int>(raw_sco.size()));
156 },
157 [resetPromise](const std::vector<uint8_t>& raw_event) {
Myles Watson47c02822023-08-28 11:53:31 -0700158 std::vector<uint8_t> reset_complete = {0x0e, 0x04, 0x01,
159 0x03, 0x0c, 0x00};
160 bool valid = raw_event.size() == 6 &&
161 raw_event[0] == reset_complete[0] &&
162 raw_event[1] == reset_complete[1] &&
163 // Don't compare the number of packets field.
164 raw_event[3] == reset_complete[3] &&
165 raw_event[4] == reset_complete[4] &&
166 raw_event[5] == reset_complete[5];
Myles Watson65b47f52023-01-26 12:59:06 -0800167 if (valid) {
168 resetPromise->set_value();
169 } else {
170 ALOGI("Discarding %d bytes with event type",
171 static_cast<int>(raw_event.size()));
172 }
173 },
174 [](const std::vector<uint8_t>& raw_iso) {
175 ALOGI("Discarding %d bytes with iso type",
176 static_cast<int>(raw_iso.size()));
177 },
178 [this]() {
179 ALOGI("HCI socket device disconnected while waiting for reset");
180 mFdWatcher.StopWatchingFileDescriptors();
181 });
182 mFdWatcher.WatchFdForNonBlockingReads(mFd,
183 [this](int) { mH4->OnDataReady(); });
184
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000185 ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
186 if (!result.isOk()) {
187 ALOGE("Error sending reset command");
188 }
Myles Watson65b47f52023-01-26 12:59:06 -0800189 auto status = resetFuture.wait_for(std::chrono::seconds(1));
190 mFdWatcher.StopWatchingFileDescriptors();
191 if (status == std::future_status::ready) {
192 ALOGI("HCI Reset successful");
193 } else {
194 ALOGE("HCI Reset Response not received in one second");
195 }
196
197 resetPromise.reset();
198}
199
Myles Watsonefa25d72022-10-03 16:27:32 -0700200ndk::ScopedAStatus BluetoothHci::initialize(
201 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
202 ALOGI(__func__);
Myles Watson6d5e7722022-09-30 06:22:43 -0700203
Myles Watson65b47f52023-01-26 12:59:06 -0800204 if (cb == nullptr) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700205 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
206 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
207 }
208
Myles Watson65b47f52023-01-26 12:59:06 -0800209 HalState old_state = HalState::READY;
210 {
211 std::lock_guard<std::mutex> guard(mStateMutex);
212 if (mState != HalState::READY) {
213 old_state = mState;
214 } else {
215 mState = HalState::INITIALIZING;
216 }
217 }
218
219 if (old_state != HalState::READY) {
220 ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
221 close();
222 cb->initializationComplete(Status::ALREADY_INITIALIZED);
223 return ndk::ScopedAStatus::ok();
224 }
225
226 mCb = cb;
Myles Watsonefa25d72022-10-03 16:27:32 -0700227 management_.reset(new NetBluetoothMgmt);
228 mFd = management_->openHci();
229 if (mFd < 0) {
230 management_.reset();
231
232 ALOGI("Unable to open Linux interface, trying default path.");
233 mFd = getFdFromDevPath();
234 if (mFd < 0) {
yanggang.yang6ebe2512023-05-31 13:59:04 +0800235 mState = HalState::READY;
Myles Watson65b47f52023-01-26 12:59:06 -0800236 cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
237 return ndk::ScopedAStatus::ok();
Myles Watsonefa25d72022-10-03 16:27:32 -0700238 }
239 }
240
Myles Watson6d5e7722022-09-30 06:22:43 -0700241 mDeathRecipient->LinkToDeath(mCb);
242
Henri Chataing1267ff22023-08-09 22:38:24 +0000243 // TODO: HCI Reset on emulators since the bluetooth controller
244 // cannot be powered on/off during the HAL setup; and the stack
245 // might received spurious packets/events during boottime.
246 // Proper solution would be to use bt-virtio or vsock to better
247 // control the link to rootcanal and the controller lifetime.
248 const std::string kBoardProperty = "ro.product.board";
249 const std::string kCuttlefishBoard = "cutf";
250 auto board_name = GetSystemProperty(kBoardProperty);
251 if (board_name.has_value() && (
252 starts_with(board_name.value(), "cutf") ||
253 starts_with(board_name.value(), "goldfish"))) {
254 reset();
255 }
Myles Watson65b47f52023-01-26 12:59:06 -0800256
Myles Watson6d5e7722022-09-30 06:22:43 -0700257 mH4 = std::make_shared<H4Protocol>(
258 mFd,
259 [](const std::vector<uint8_t>& /* raw_command */) {
260 LOG_ALWAYS_FATAL("Unexpected command!");
261 },
David Duartea58b79d2023-01-19 18:14:32 +0000262 [this](const std::vector<uint8_t>& raw_acl) {
263 mCb->aclDataReceived(raw_acl);
264 },
265 [this](const std::vector<uint8_t>& raw_sco) {
266 mCb->scoDataReceived(raw_sco);
267 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700268 [this](const std::vector<uint8_t>& raw_event) {
269 mCb->hciEventReceived(raw_event);
270 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700271 [this](const std::vector<uint8_t>& raw_iso) {
David Duartea58b79d2023-01-19 18:14:32 +0000272 mCb->isoDataReceived(raw_iso);
Myles Watson6d5e7722022-09-30 06:22:43 -0700273 },
274 [this]() {
275 ALOGI("HCI socket device disconnected");
276 mFdWatcher.StopWatchingFileDescriptors();
277 });
278 mFdWatcher.WatchFdForNonBlockingReads(mFd,
279 [this](int) { mH4->OnDataReady(); });
Myles Watsonefa25d72022-10-03 16:27:32 -0700280
Myles Watson65b47f52023-01-26 12:59:06 -0800281 {
282 std::lock_guard<std::mutex> guard(mStateMutex);
283 mState = HalState::ONE_CLIENT;
284 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700285 ALOGI("initialization complete");
286 auto status = mCb->initializationComplete(Status::SUCCESS);
287 if (!status.isOk()) {
288 if (!mDeathRecipient->getHasDied()) {
289 ALOGE("Error sending init callback, but no death notification");
290 }
291 close();
292 return ndk::ScopedAStatus::fromServiceSpecificError(
293 STATUS_FAILED_TRANSACTION);
294 }
295
Myles Watson6d5e7722022-09-30 06:22:43 -0700296 return ndk::ScopedAStatus::ok();
297}
298
299ndk::ScopedAStatus BluetoothHci::close() {
300 ALOGI(__func__);
Myles Watson65b47f52023-01-26 12:59:06 -0800301 {
302 std::lock_guard<std::mutex> guard(mStateMutex);
303 if (mState != HalState::ONE_CLIENT) {
Myles Watson47c02822023-08-28 11:53:31 -0700304 LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
305 "mState is INITIALIZING");
Myles Watson65b47f52023-01-26 12:59:06 -0800306 ALOGI("Already closed");
307 return ndk::ScopedAStatus::ok();
308 }
309 mState = HalState::CLOSING;
310 }
311
Myles Watson6d5e7722022-09-30 06:22:43 -0700312 mFdWatcher.StopWatchingFileDescriptors();
Myles Watson65b47f52023-01-26 12:59:06 -0800313
Myles Watsonefa25d72022-10-03 16:27:32 -0700314 if (management_) {
315 management_->closeHci();
316 } else {
317 ::close(mFd);
318 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700319
Myles Watson65b47f52023-01-26 12:59:06 -0800320 {
321 std::lock_guard<std::mutex> guard(mStateMutex);
322 mState = HalState::READY;
yanggang.yang886074d2023-10-26 17:24:56 +0800323 mH4 = nullptr;
Myles Watson65b47f52023-01-26 12:59:06 -0800324 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700325 return ndk::ScopedAStatus::ok();
326}
327
328ndk::ScopedAStatus BluetoothHci::sendHciCommand(
329 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000330 return send(PacketType::COMMAND, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700331}
332
333ndk::ScopedAStatus BluetoothHci::sendAclData(
334 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000335 return send(PacketType::ACL_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700336}
337
338ndk::ScopedAStatus BluetoothHci::sendScoData(
339 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000340 return send(PacketType::SCO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700341}
342
343ndk::ScopedAStatus BluetoothHci::sendIsoData(
344 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000345 return send(PacketType::ISO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700346}
347
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000348ndk::ScopedAStatus BluetoothHci::send(PacketType type,
349 const std::vector<uint8_t>& v) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000350 if (v.empty()) {
351 ALOGE("Packet is empty, no data was found to be sent");
352 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
353 }
yanggang.yang886074d2023-10-26 17:24:56 +0800354
355 std::lock_guard<std::mutex> guard(mStateMutex);
356 if (mH4 == nullptr) {
357 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
358 }
359
Myles Watson6d5e7722022-09-30 06:22:43 -0700360 mH4->Send(type, v);
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000361 return ndk::ScopedAStatus::ok();
Myles Watson6d5e7722022-09-30 06:22:43 -0700362}
363
364} // namespace aidl::android::hardware::bluetooth::impl