blob: 940f2adc5bb47dd41b612d03210a53af79c99ab1 [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 }
120 if (int ret = SetTerminalRaw(mFd) < 0) {
121 ALOGE("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
122 strerror(errno));
Myles Watsonefa25d72022-10-03 16:27:32 -0700123 ::close(fd);
124 return -1;
Myles Watson6d5e7722022-09-30 06:22:43 -0700125 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700126 return fd;
127}
128
Myles Watson65b47f52023-01-26 12:59:06 -0800129void BluetoothHci::reset() {
130 // Send a reset command and wait until the command complete comes back.
131
132 std::vector<uint8_t> reset;
133 ::bluetooth::packet::BitInserter bi{reset};
134 ::bluetooth::hci::ResetBuilder::Create()->Serialize(bi);
135
136 auto resetPromise = std::make_shared<std::promise<void>>();
137 auto resetFuture = resetPromise->get_future();
138
139 mH4 = std::make_shared<H4Protocol>(
140 mFd,
141 [](const std::vector<uint8_t>& raw_command) {
142 ALOGI("Discarding %d bytes with command type",
143 static_cast<int>(raw_command.size()));
144 },
145 [](const std::vector<uint8_t>& raw_acl) {
146 ALOGI("Discarding %d bytes with acl type",
147 static_cast<int>(raw_acl.size()));
148 },
149 [](const std::vector<uint8_t>& raw_sco) {
150 ALOGI("Discarding %d bytes with sco type",
151 static_cast<int>(raw_sco.size()));
152 },
153 [resetPromise](const std::vector<uint8_t>& raw_event) {
154 bool valid = ::bluetooth::hci::ResetCompleteView::Create(
155 ::bluetooth::hci::CommandCompleteView::Create(
156 ::bluetooth::hci::EventView::Create(
157 ::bluetooth::hci::PacketView<true>(
158 std::make_shared<std::vector<uint8_t>>(
159 raw_event)))))
160 .IsValid();
161 if (valid) {
162 resetPromise->set_value();
163 } else {
164 ALOGI("Discarding %d bytes with event type",
165 static_cast<int>(raw_event.size()));
166 }
167 },
168 [](const std::vector<uint8_t>& raw_iso) {
169 ALOGI("Discarding %d bytes with iso type",
170 static_cast<int>(raw_iso.size()));
171 },
172 [this]() {
173 ALOGI("HCI socket device disconnected while waiting for reset");
174 mFdWatcher.StopWatchingFileDescriptors();
175 });
176 mFdWatcher.WatchFdForNonBlockingReads(mFd,
177 [this](int) { mH4->OnDataReady(); });
178
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000179 ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
180 if (!result.isOk()) {
181 ALOGE("Error sending reset command");
182 }
Myles Watson65b47f52023-01-26 12:59:06 -0800183 auto status = resetFuture.wait_for(std::chrono::seconds(1));
184 mFdWatcher.StopWatchingFileDescriptors();
185 if (status == std::future_status::ready) {
186 ALOGI("HCI Reset successful");
187 } else {
188 ALOGE("HCI Reset Response not received in one second");
189 }
190
191 resetPromise.reset();
192}
193
Myles Watsonefa25d72022-10-03 16:27:32 -0700194ndk::ScopedAStatus BluetoothHci::initialize(
195 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
196 ALOGI(__func__);
Myles Watson6d5e7722022-09-30 06:22:43 -0700197
Myles Watson65b47f52023-01-26 12:59:06 -0800198 if (cb == nullptr) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700199 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
200 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
201 }
202
Myles Watson65b47f52023-01-26 12:59:06 -0800203 HalState old_state = HalState::READY;
204 {
205 std::lock_guard<std::mutex> guard(mStateMutex);
206 if (mState != HalState::READY) {
207 old_state = mState;
208 } else {
209 mState = HalState::INITIALIZING;
210 }
211 }
212
213 if (old_state != HalState::READY) {
214 ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
215 close();
216 cb->initializationComplete(Status::ALREADY_INITIALIZED);
217 return ndk::ScopedAStatus::ok();
218 }
219
220 mCb = cb;
Myles Watsonefa25d72022-10-03 16:27:32 -0700221 management_.reset(new NetBluetoothMgmt);
222 mFd = management_->openHci();
223 if (mFd < 0) {
224 management_.reset();
225
226 ALOGI("Unable to open Linux interface, trying default path.");
227 mFd = getFdFromDevPath();
228 if (mFd < 0) {
Myles Watson65b47f52023-01-26 12:59:06 -0800229 cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
230 return ndk::ScopedAStatus::ok();
Myles Watsonefa25d72022-10-03 16:27:32 -0700231 }
232 }
233
Myles Watson6d5e7722022-09-30 06:22:43 -0700234 mDeathRecipient->LinkToDeath(mCb);
235
Myles Watson65b47f52023-01-26 12:59:06 -0800236 // TODO: This should not be necessary when the device implements rfkill.
237 reset();
238
Myles Watson6d5e7722022-09-30 06:22:43 -0700239 mH4 = std::make_shared<H4Protocol>(
240 mFd,
241 [](const std::vector<uint8_t>& /* raw_command */) {
242 LOG_ALWAYS_FATAL("Unexpected command!");
243 },
David Duartea58b79d2023-01-19 18:14:32 +0000244 [this](const std::vector<uint8_t>& raw_acl) {
245 mCb->aclDataReceived(raw_acl);
246 },
247 [this](const std::vector<uint8_t>& raw_sco) {
248 mCb->scoDataReceived(raw_sco);
249 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700250 [this](const std::vector<uint8_t>& raw_event) {
251 mCb->hciEventReceived(raw_event);
252 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700253 [this](const std::vector<uint8_t>& raw_iso) {
David Duartea58b79d2023-01-19 18:14:32 +0000254 mCb->isoDataReceived(raw_iso);
Myles Watson6d5e7722022-09-30 06:22:43 -0700255 },
256 [this]() {
257 ALOGI("HCI socket device disconnected");
258 mFdWatcher.StopWatchingFileDescriptors();
259 });
260 mFdWatcher.WatchFdForNonBlockingReads(mFd,
261 [this](int) { mH4->OnDataReady(); });
Myles Watsonefa25d72022-10-03 16:27:32 -0700262
Myles Watson65b47f52023-01-26 12:59:06 -0800263 {
264 std::lock_guard<std::mutex> guard(mStateMutex);
265 mState = HalState::ONE_CLIENT;
266 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700267 ALOGI("initialization complete");
268 auto status = mCb->initializationComplete(Status::SUCCESS);
269 if (!status.isOk()) {
270 if (!mDeathRecipient->getHasDied()) {
271 ALOGE("Error sending init callback, but no death notification");
272 }
273 close();
274 return ndk::ScopedAStatus::fromServiceSpecificError(
275 STATUS_FAILED_TRANSACTION);
276 }
277
Myles Watson6d5e7722022-09-30 06:22:43 -0700278 return ndk::ScopedAStatus::ok();
279}
280
281ndk::ScopedAStatus BluetoothHci::close() {
282 ALOGI(__func__);
Myles Watson65b47f52023-01-26 12:59:06 -0800283 {
284 std::lock_guard<std::mutex> guard(mStateMutex);
285 if (mState != HalState::ONE_CLIENT) {
286 ALOGI("Already closed");
287 return ndk::ScopedAStatus::ok();
288 }
289 mState = HalState::CLOSING;
290 }
291
Myles Watson6d5e7722022-09-30 06:22:43 -0700292 mFdWatcher.StopWatchingFileDescriptors();
Myles Watson65b47f52023-01-26 12:59:06 -0800293
Myles Watsonefa25d72022-10-03 16:27:32 -0700294 if (management_) {
295 management_->closeHci();
296 } else {
297 ::close(mFd);
298 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700299
Myles Watson65b47f52023-01-26 12:59:06 -0800300 {
301 std::lock_guard<std::mutex> guard(mStateMutex);
302 mState = HalState::READY;
303 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700304 return ndk::ScopedAStatus::ok();
305}
306
307ndk::ScopedAStatus BluetoothHci::sendHciCommand(
308 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000309 return send(PacketType::COMMAND, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700310}
311
312ndk::ScopedAStatus BluetoothHci::sendAclData(
313 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000314 return send(PacketType::ACL_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700315}
316
317ndk::ScopedAStatus BluetoothHci::sendScoData(
318 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000319 return send(PacketType::SCO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700320}
321
322ndk::ScopedAStatus BluetoothHci::sendIsoData(
323 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000324 return send(PacketType::ISO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700325}
326
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000327ndk::ScopedAStatus BluetoothHci::send(PacketType type,
328 const std::vector<uint8_t>& v) {
329 if (mH4 == nullptr) {
330 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
331 }
332 if (v.empty()) {
333 ALOGE("Packet is empty, no data was found to be sent");
334 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
335 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700336 mH4->Send(type, v);
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000337 return ndk::ScopedAStatus::ok();
Myles Watson6d5e7722022-09-30 06:22:43 -0700338}
339
340} // namespace aidl::android::hardware::bluetooth::impl