blob: d4e4b34c6ef592d88bdc03d98c5983ac2655b386 [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
179 send(PacketType::COMMAND, reset);
180 auto status = resetFuture.wait_for(std::chrono::seconds(1));
181 mFdWatcher.StopWatchingFileDescriptors();
182 if (status == std::future_status::ready) {
183 ALOGI("HCI Reset successful");
184 } else {
185 ALOGE("HCI Reset Response not received in one second");
186 }
187
188 resetPromise.reset();
189}
190
Myles Watsonefa25d72022-10-03 16:27:32 -0700191ndk::ScopedAStatus BluetoothHci::initialize(
192 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
193 ALOGI(__func__);
Myles Watson6d5e7722022-09-30 06:22:43 -0700194
Myles Watson65b47f52023-01-26 12:59:06 -0800195 if (cb == nullptr) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700196 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
197 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
198 }
199
Myles Watson65b47f52023-01-26 12:59:06 -0800200 HalState old_state = HalState::READY;
201 {
202 std::lock_guard<std::mutex> guard(mStateMutex);
203 if (mState != HalState::READY) {
204 old_state = mState;
205 } else {
206 mState = HalState::INITIALIZING;
207 }
208 }
209
210 if (old_state != HalState::READY) {
211 ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
212 close();
213 cb->initializationComplete(Status::ALREADY_INITIALIZED);
214 return ndk::ScopedAStatus::ok();
215 }
216
217 mCb = cb;
Myles Watsonefa25d72022-10-03 16:27:32 -0700218 management_.reset(new NetBluetoothMgmt);
219 mFd = management_->openHci();
220 if (mFd < 0) {
221 management_.reset();
222
223 ALOGI("Unable to open Linux interface, trying default path.");
224 mFd = getFdFromDevPath();
225 if (mFd < 0) {
Myles Watson65b47f52023-01-26 12:59:06 -0800226 cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
227 return ndk::ScopedAStatus::ok();
Myles Watsonefa25d72022-10-03 16:27:32 -0700228 }
229 }
230
Myles Watson6d5e7722022-09-30 06:22:43 -0700231 mDeathRecipient->LinkToDeath(mCb);
232
Myles Watson65b47f52023-01-26 12:59:06 -0800233 // TODO: This should not be necessary when the device implements rfkill.
234 reset();
235
Myles Watson6d5e7722022-09-30 06:22:43 -0700236 mH4 = std::make_shared<H4Protocol>(
237 mFd,
238 [](const std::vector<uint8_t>& /* raw_command */) {
239 LOG_ALWAYS_FATAL("Unexpected command!");
240 },
David Duartea58b79d2023-01-19 18:14:32 +0000241 [this](const std::vector<uint8_t>& raw_acl) {
242 mCb->aclDataReceived(raw_acl);
243 },
244 [this](const std::vector<uint8_t>& raw_sco) {
245 mCb->scoDataReceived(raw_sco);
246 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700247 [this](const std::vector<uint8_t>& raw_event) {
248 mCb->hciEventReceived(raw_event);
249 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700250 [this](const std::vector<uint8_t>& raw_iso) {
David Duartea58b79d2023-01-19 18:14:32 +0000251 mCb->isoDataReceived(raw_iso);
Myles Watson6d5e7722022-09-30 06:22:43 -0700252 },
253 [this]() {
254 ALOGI("HCI socket device disconnected");
255 mFdWatcher.StopWatchingFileDescriptors();
256 });
257 mFdWatcher.WatchFdForNonBlockingReads(mFd,
258 [this](int) { mH4->OnDataReady(); });
Myles Watsonefa25d72022-10-03 16:27:32 -0700259
Myles Watson65b47f52023-01-26 12:59:06 -0800260 {
261 std::lock_guard<std::mutex> guard(mStateMutex);
262 mState = HalState::ONE_CLIENT;
263 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700264 ALOGI("initialization complete");
265 auto status = mCb->initializationComplete(Status::SUCCESS);
266 if (!status.isOk()) {
267 if (!mDeathRecipient->getHasDied()) {
268 ALOGE("Error sending init callback, but no death notification");
269 }
270 close();
271 return ndk::ScopedAStatus::fromServiceSpecificError(
272 STATUS_FAILED_TRANSACTION);
273 }
274
Myles Watson6d5e7722022-09-30 06:22:43 -0700275 return ndk::ScopedAStatus::ok();
276}
277
278ndk::ScopedAStatus BluetoothHci::close() {
279 ALOGI(__func__);
Myles Watson65b47f52023-01-26 12:59:06 -0800280 {
281 std::lock_guard<std::mutex> guard(mStateMutex);
282 if (mState != HalState::ONE_CLIENT) {
283 ALOGI("Already closed");
284 return ndk::ScopedAStatus::ok();
285 }
286 mState = HalState::CLOSING;
287 }
288
Myles Watson6d5e7722022-09-30 06:22:43 -0700289 mFdWatcher.StopWatchingFileDescriptors();
Myles Watson65b47f52023-01-26 12:59:06 -0800290
Myles Watsonefa25d72022-10-03 16:27:32 -0700291 if (management_) {
292 management_->closeHci();
293 } else {
294 ::close(mFd);
295 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700296
Myles Watson65b47f52023-01-26 12:59:06 -0800297 {
298 std::lock_guard<std::mutex> guard(mStateMutex);
299 mState = HalState::READY;
300 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700301 return ndk::ScopedAStatus::ok();
302}
303
304ndk::ScopedAStatus BluetoothHci::sendHciCommand(
305 const std::vector<uint8_t>& packet) {
306 send(PacketType::COMMAND, packet);
307 return ndk::ScopedAStatus::ok();
308}
309
310ndk::ScopedAStatus BluetoothHci::sendAclData(
311 const std::vector<uint8_t>& packet) {
312 send(PacketType::ACL_DATA, packet);
313 return ndk::ScopedAStatus::ok();
314}
315
316ndk::ScopedAStatus BluetoothHci::sendScoData(
317 const std::vector<uint8_t>& packet) {
318 send(PacketType::SCO_DATA, packet);
319 return ndk::ScopedAStatus::ok();
320}
321
322ndk::ScopedAStatus BluetoothHci::sendIsoData(
323 const std::vector<uint8_t>& packet) {
324 send(PacketType::ISO_DATA, packet);
325 return ndk::ScopedAStatus::ok();
326}
327
328void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
329 mH4->Send(type, v);
330}
331
332} // namespace aidl::android::hardware::bluetooth::impl