blob: 18a371db0c5219c3ba5bd94fb5ce503a2bff3b67 [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
Myles Watson65b47f52023-01-26 12:59:06 -080032// TODO: Remove custom logging defines from PDL packets.
33#undef LOG_INFO
34#undef LOG_DEBUG
35#include "hci/hci_packets.h"
36
Myles Watson6d5e7722022-09-30 06:22:43 -070037namespace {
38int SetTerminalRaw(int fd) {
39 termios terminal_settings;
40 int rval = tcgetattr(fd, &terminal_settings);
41 if (rval < 0) {
42 return rval;
43 }
44 cfmakeraw(&terminal_settings);
45 rval = tcsetattr(fd, TCSANOW, &terminal_settings);
46 return rval;
47}
48} // namespace
49
50using namespace ::android::hardware::bluetooth::hci;
51using namespace ::android::hardware::bluetooth::async;
Myles Watsonefa25d72022-10-03 16:27:32 -070052using aidl::android::hardware::bluetooth::Status;
Myles Watson6d5e7722022-09-30 06:22:43 -070053
54namespace aidl::android::hardware::bluetooth::impl {
55
56void OnDeath(void* cookie);
57
58class BluetoothDeathRecipient {
59 public:
60 BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
61
62 void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
63 mCb = cb;
64 clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
65 auto linkToDeathReturnStatus = AIBinder_linkToDeath(
66 mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
67 LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
68 "Unable to link to death recipient");
69 }
70
71 void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
72 LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
73 }
74
75 void serviceDied() {
76 if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
77 ALOGE("Bluetooth remote service has died");
78 } else {
79 ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
80 return;
81 }
Myles Watson65b47f52023-01-26 12:59:06 -080082 {
83 std::lock_guard<std::mutex> guard(mHasDiedMutex);
84 has_died_ = true;
85 }
Myles Watson6d5e7722022-09-30 06:22:43 -070086 mHci->close();
87 }
88 BluetoothHci* mHci;
89 std::shared_ptr<IBluetoothHciCallbacks> mCb;
90 AIBinder_DeathRecipient* clientDeathRecipient_;
Myles Watson65b47f52023-01-26 12:59:06 -080091 bool getHasDied() {
92 std::lock_guard<std::mutex> guard(mHasDiedMutex);
93 return has_died_;
94 }
Myles Watson6d5e7722022-09-30 06:22:43 -070095
96 private:
Myles Watson65b47f52023-01-26 12:59:06 -080097 std::mutex mHasDiedMutex;
Myles Watson8678c752022-11-03 10:41:44 -070098 bool has_died_{false};
Myles Watson6d5e7722022-09-30 06:22:43 -070099};
100
101void OnDeath(void* cookie) {
102 auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
103 death_recipient->serviceDied();
104}
105
106BluetoothHci::BluetoothHci(const std::string& dev_path) {
107 char property_bytes[PROPERTY_VALUE_MAX];
108 property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
109 mDevPath = std::string(property_bytes);
110 mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
111}
112
Myles Watsonefa25d72022-10-03 16:27:32 -0700113int BluetoothHci::getFdFromDevPath() {
114 int fd = open(mDevPath.c_str(), O_RDWR);
115 if (fd < 0) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700116 ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
117 strerror(errno));
Myles Watsonefa25d72022-10-03 16:27:32 -0700118 return fd;
Myles Watson6d5e7722022-09-30 06:22:43 -0700119 }
yanggang.yangeb744bc2023-04-21 11:05:42 +0800120 if (int ret = SetTerminalRaw(fd) < 0) {
121 ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
Myles Watson6d5e7722022-09-30 06:22:43 -0700122 strerror(errno));
Myles Watson6d5e7722022-09-30 06:22:43 -0700123 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700124 return fd;
125}
126
Myles Watson65b47f52023-01-26 12:59:06 -0800127void BluetoothHci::reset() {
128 // Send a reset command and wait until the command complete comes back.
129
130 std::vector<uint8_t> reset;
131 ::bluetooth::packet::BitInserter bi{reset};
132 ::bluetooth::hci::ResetBuilder::Create()->Serialize(bi);
133
134 auto resetPromise = std::make_shared<std::promise<void>>();
135 auto resetFuture = resetPromise->get_future();
136
137 mH4 = std::make_shared<H4Protocol>(
138 mFd,
139 [](const std::vector<uint8_t>& raw_command) {
140 ALOGI("Discarding %d bytes with command type",
141 static_cast<int>(raw_command.size()));
142 },
143 [](const std::vector<uint8_t>& raw_acl) {
144 ALOGI("Discarding %d bytes with acl type",
145 static_cast<int>(raw_acl.size()));
146 },
147 [](const std::vector<uint8_t>& raw_sco) {
148 ALOGI("Discarding %d bytes with sco type",
149 static_cast<int>(raw_sco.size()));
150 },
151 [resetPromise](const std::vector<uint8_t>& raw_event) {
152 bool valid = ::bluetooth::hci::ResetCompleteView::Create(
153 ::bluetooth::hci::CommandCompleteView::Create(
154 ::bluetooth::hci::EventView::Create(
155 ::bluetooth::hci::PacketView<true>(
156 std::make_shared<std::vector<uint8_t>>(
157 raw_event)))))
158 .IsValid();
159 if (valid) {
160 resetPromise->set_value();
161 } else {
162 ALOGI("Discarding %d bytes with event type",
163 static_cast<int>(raw_event.size()));
164 }
165 },
166 [](const std::vector<uint8_t>& raw_iso) {
167 ALOGI("Discarding %d bytes with iso type",
168 static_cast<int>(raw_iso.size()));
169 },
170 [this]() {
171 ALOGI("HCI socket device disconnected while waiting for reset");
172 mFdWatcher.StopWatchingFileDescriptors();
173 });
174 mFdWatcher.WatchFdForNonBlockingReads(mFd,
175 [this](int) { mH4->OnDataReady(); });
176
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000177 ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
178 if (!result.isOk()) {
179 ALOGE("Error sending reset command");
180 }
Myles Watson65b47f52023-01-26 12:59:06 -0800181 auto status = resetFuture.wait_for(std::chrono::seconds(1));
182 mFdWatcher.StopWatchingFileDescriptors();
183 if (status == std::future_status::ready) {
184 ALOGI("HCI Reset successful");
185 } else {
186 ALOGE("HCI Reset Response not received in one second");
187 }
188
189 resetPromise.reset();
190}
191
Myles Watsonefa25d72022-10-03 16:27:32 -0700192ndk::ScopedAStatus BluetoothHci::initialize(
193 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
194 ALOGI(__func__);
Myles Watson6d5e7722022-09-30 06:22:43 -0700195
Myles Watson65b47f52023-01-26 12:59:06 -0800196 if (cb == nullptr) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700197 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
198 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
199 }
200
Myles Watson65b47f52023-01-26 12:59:06 -0800201 HalState old_state = HalState::READY;
202 {
203 std::lock_guard<std::mutex> guard(mStateMutex);
204 if (mState != HalState::READY) {
205 old_state = mState;
206 } else {
207 mState = HalState::INITIALIZING;
208 }
209 }
210
211 if (old_state != HalState::READY) {
212 ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
213 close();
214 cb->initializationComplete(Status::ALREADY_INITIALIZED);
215 return ndk::ScopedAStatus::ok();
216 }
217
218 mCb = cb;
Myles Watsonefa25d72022-10-03 16:27:32 -0700219 management_.reset(new NetBluetoothMgmt);
220 mFd = management_->openHci();
221 if (mFd < 0) {
222 management_.reset();
223
224 ALOGI("Unable to open Linux interface, trying default path.");
225 mFd = getFdFromDevPath();
226 if (mFd < 0) {
Myles Watson65b47f52023-01-26 12:59:06 -0800227 cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
228 return ndk::ScopedAStatus::ok();
Myles Watsonefa25d72022-10-03 16:27:32 -0700229 }
230 }
231
Myles Watson6d5e7722022-09-30 06:22:43 -0700232 mDeathRecipient->LinkToDeath(mCb);
233
Myles Watson65b47f52023-01-26 12:59:06 -0800234 // TODO: This should not be necessary when the device implements rfkill.
235 reset();
236
Myles Watson6d5e7722022-09-30 06:22:43 -0700237 mH4 = std::make_shared<H4Protocol>(
238 mFd,
239 [](const std::vector<uint8_t>& /* raw_command */) {
240 LOG_ALWAYS_FATAL("Unexpected command!");
241 },
David Duartea58b79d2023-01-19 18:14:32 +0000242 [this](const std::vector<uint8_t>& raw_acl) {
243 mCb->aclDataReceived(raw_acl);
244 },
245 [this](const std::vector<uint8_t>& raw_sco) {
246 mCb->scoDataReceived(raw_sco);
247 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700248 [this](const std::vector<uint8_t>& raw_event) {
249 mCb->hciEventReceived(raw_event);
250 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700251 [this](const std::vector<uint8_t>& raw_iso) {
David Duartea58b79d2023-01-19 18:14:32 +0000252 mCb->isoDataReceived(raw_iso);
Myles Watson6d5e7722022-09-30 06:22:43 -0700253 },
254 [this]() {
255 ALOGI("HCI socket device disconnected");
256 mFdWatcher.StopWatchingFileDescriptors();
257 });
258 mFdWatcher.WatchFdForNonBlockingReads(mFd,
259 [this](int) { mH4->OnDataReady(); });
Myles Watsonefa25d72022-10-03 16:27:32 -0700260
Myles Watson65b47f52023-01-26 12:59:06 -0800261 {
262 std::lock_guard<std::mutex> guard(mStateMutex);
263 mState = HalState::ONE_CLIENT;
264 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700265 ALOGI("initialization complete");
266 auto status = mCb->initializationComplete(Status::SUCCESS);
267 if (!status.isOk()) {
268 if (!mDeathRecipient->getHasDied()) {
269 ALOGE("Error sending init callback, but no death notification");
270 }
271 close();
272 return ndk::ScopedAStatus::fromServiceSpecificError(
273 STATUS_FAILED_TRANSACTION);
274 }
275
Myles Watson6d5e7722022-09-30 06:22:43 -0700276 return ndk::ScopedAStatus::ok();
277}
278
279ndk::ScopedAStatus BluetoothHci::close() {
280 ALOGI(__func__);
Myles Watson65b47f52023-01-26 12:59:06 -0800281 {
282 std::lock_guard<std::mutex> guard(mStateMutex);
283 if (mState != HalState::ONE_CLIENT) {
284 ALOGI("Already closed");
285 return ndk::ScopedAStatus::ok();
286 }
287 mState = HalState::CLOSING;
288 }
289
Myles Watson6d5e7722022-09-30 06:22:43 -0700290 mFdWatcher.StopWatchingFileDescriptors();
Myles Watson65b47f52023-01-26 12:59:06 -0800291
Myles Watsonefa25d72022-10-03 16:27:32 -0700292 if (management_) {
293 management_->closeHci();
294 } else {
295 ::close(mFd);
296 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700297
Myles Watson65b47f52023-01-26 12:59:06 -0800298 {
299 std::lock_guard<std::mutex> guard(mStateMutex);
300 mState = HalState::READY;
301 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700302 return ndk::ScopedAStatus::ok();
303}
304
305ndk::ScopedAStatus BluetoothHci::sendHciCommand(
306 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000307 return send(PacketType::COMMAND, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700308}
309
310ndk::ScopedAStatus BluetoothHci::sendAclData(
311 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000312 return send(PacketType::ACL_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700313}
314
315ndk::ScopedAStatus BluetoothHci::sendScoData(
316 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000317 return send(PacketType::SCO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700318}
319
320ndk::ScopedAStatus BluetoothHci::sendIsoData(
321 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000322 return send(PacketType::ISO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700323}
324
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000325ndk::ScopedAStatus BluetoothHci::send(PacketType type,
326 const std::vector<uint8_t>& v) {
327 if (mH4 == nullptr) {
328 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
329 }
330 if (v.empty()) {
331 ALOGE("Packet is empty, no data was found to be sent");
332 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
333 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700334 mH4->Send(type, v);
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000335 return ndk::ScopedAStatus::ok();
Myles Watson6d5e7722022-09-30 06:22:43 -0700336}
337
338} // namespace aidl::android::hardware::bluetooth::impl