1 /*
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
32 namespace {
SetTerminalRaw(int fd)33 int 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
45 using namespace ::android::hardware::bluetooth::hci;
46 using namespace ::android::hardware::bluetooth::async;
47 using aidl::android::hardware::bluetooth::hal::Status;
48
49 namespace aidl::android::hardware::bluetooth::impl {
50
GetSystemProperty(const std::string & property)51 std::optional<std::string> GetSystemProperty(const std::string& property) {
52 std::array<char, PROPERTY_VALUE_MAX> value_array{0};
53 auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
54 if (value_len <= 0) {
55 return std::nullopt;
56 }
57 return std::string(value_array.data(), value_len);
58 }
59
starts_with(const std::string & str,const std::string & prefix)60 bool starts_with(const std::string& str, const std::string& prefix) {
61 return str.compare(0, prefix.length(), prefix) == 0;
62 }
63
BluetoothHci(const std::string & dev_path)64 BluetoothHci::BluetoothHci(const std::string& dev_path) {
65 char property_bytes[PROPERTY_VALUE_MAX];
66 property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
67 mDevPath = std::string(property_bytes);
68 }
69
getFdFromDevPath()70 int BluetoothHci::getFdFromDevPath() {
71 int fd = open(mDevPath.c_str(), O_RDWR);
72 if (fd < 0) {
73 ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
74 strerror(errno));
75 return fd;
76 }
77 if (int ret = SetTerminalRaw(fd) < 0) {
78 ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
79 strerror(errno));
80 }
81 return fd;
82 }
83
reset()84 void BluetoothHci::reset() {
85 // Send a reset command and wait until the command complete comes back.
86
87 std::vector<uint8_t> reset = {0x03, 0x0c, 0x00};
88
89 auto resetPromise = std::make_shared<std::promise<void>>();
90 auto resetFuture = resetPromise->get_future();
91
92 mH4 = std::make_shared<H4Protocol>(
93 mFd,
94 [](const std::vector<uint8_t>& raw_command) {
95 ALOGI("Discarding %d bytes with command type",
96 static_cast<int>(raw_command.size()));
97 },
98 [](const std::vector<uint8_t>& raw_acl) {
99 ALOGI("Discarding %d bytes with acl type",
100 static_cast<int>(raw_acl.size()));
101 },
102 [](const std::vector<uint8_t>& raw_sco) {
103 ALOGI("Discarding %d bytes with sco type",
104 static_cast<int>(raw_sco.size()));
105 },
106 [resetPromise](const std::vector<uint8_t>& raw_event) {
107 std::vector<uint8_t> reset_complete = {0x0e, 0x04, 0x01,
108 0x03, 0x0c, 0x00};
109 bool valid = raw_event.size() == 6 &&
110 raw_event[0] == reset_complete[0] &&
111 raw_event[1] == reset_complete[1] &&
112 // Don't compare the number of packets field.
113 raw_event[3] == reset_complete[3] &&
114 raw_event[4] == reset_complete[4] &&
115 raw_event[5] == reset_complete[5];
116 if (valid) {
117 resetPromise->set_value();
118 } else {
119 ALOGI("Discarding %d bytes with event type",
120 static_cast<int>(raw_event.size()));
121 }
122 },
123 [](const std::vector<uint8_t>& raw_iso) {
124 ALOGI("Discarding %d bytes with iso type",
125 static_cast<int>(raw_iso.size()));
126 },
127 [this]() {
128 ALOGI("HCI socket device disconnected while waiting for reset");
129 mFdWatcher.StopWatchingFileDescriptors();
130 });
131 mFdWatcher.WatchFdForNonBlockingReads(mFd,
132 [this](int) { mH4->OnDataReady(); });
133
134 send(PacketType::COMMAND, reset);
135 auto status = resetFuture.wait_for(std::chrono::seconds(1));
136 mFdWatcher.StopWatchingFileDescriptors();
137 if (status == std::future_status::ready) {
138 ALOGI("HCI Reset successful");
139 } else {
140 ALOGE("HCI Reset Response not received in one second");
141 }
142
143 resetPromise.reset();
144 }
145
initialize(const std::shared_ptr<hal::IBluetoothHciCallbacks> & cb)146 void BluetoothHci::initialize(
147 const std::shared_ptr<hal::IBluetoothHciCallbacks>& cb) {
148 ALOGI(__func__);
149
150 if (cb == nullptr) {
151 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
152 abort();
153 }
154
155 HalState old_state = HalState::READY;
156 {
157 std::lock_guard<std::mutex> guard(mStateMutex);
158 if (mState != HalState::READY) {
159 old_state = mState;
160 } else {
161 mState = HalState::INITIALIZING;
162 }
163 }
164
165 if (old_state != HalState::READY) {
166 ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
167 close();
168 cb->initializationComplete(Status::ALREADY_INITIALIZED);
169 }
170
171 mCb = cb;
172 management_.reset(new NetBluetoothMgmt);
173 mFd = management_->openHci();
174 if (mFd < 0) {
175 management_.reset();
176
177 ALOGI("Unable to open Linux interface, trying default path.");
178 mFd = getFdFromDevPath();
179 if (mFd < 0) {
180 mState = HalState::READY;
181 cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
182 }
183 }
184
185 // TODO: HCI Reset on emulators since the bluetooth controller
186 // cannot be powered on/off during the HAL setup; and the stack
187 // might received spurious packets/events during boottime.
188 // Proper solution would be to use bt-virtio or vsock to better
189 // control the link to rootcanal and the controller lifetime.
190 const std::string kBoardProperty = "ro.product.board";
191 const std::string kCuttlefishBoard = "cutf";
192 auto board_name = GetSystemProperty(kBoardProperty);
193 if (board_name.has_value() && (
194 starts_with(board_name.value(), "cutf") ||
195 starts_with(board_name.value(), "goldfish"))) {
196 reset();
197 }
198
199 mH4 = std::make_shared<H4Protocol>(
200 mFd,
201 [](const std::vector<uint8_t>& /* raw_command */) {
202 LOG_ALWAYS_FATAL("Unexpected command!");
203 },
204 [this](const std::vector<uint8_t>& raw_acl) {
205 mCb->aclDataReceived(raw_acl);
206 },
207 [this](const std::vector<uint8_t>& raw_sco) {
208 mCb->scoDataReceived(raw_sco);
209 },
210 [this](const std::vector<uint8_t>& raw_event) {
211 mCb->hciEventReceived(raw_event);
212 },
213 [this](const std::vector<uint8_t>& raw_iso) {
214 mCb->isoDataReceived(raw_iso);
215 },
216 [this]() {
217 ALOGI("HCI socket device disconnected");
218 mFdWatcher.StopWatchingFileDescriptors();
219 });
220 mFdWatcher.WatchFdForNonBlockingReads(mFd,
221 [this](int) { mH4->OnDataReady(); });
222
223 {
224 std::lock_guard<std::mutex> guard(mStateMutex);
225 mState = HalState::ONE_CLIENT;
226 }
227 ALOGI("initialization complete");
228 mCb->initializationComplete(Status::SUCCESS);
229 }
230
close()231 void BluetoothHci::close() {
232 ALOGI(__func__);
233 {
234 std::lock_guard<std::mutex> guard(mStateMutex);
235 if (mState != HalState::ONE_CLIENT) {
236 LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
237 "mState is INITIALIZING");
238 ALOGI("Already closed");
239 }
240 mState = HalState::CLOSING;
241 }
242
243 mFdWatcher.StopWatchingFileDescriptors();
244
245 if (management_) {
246 management_->closeHci();
247 } else {
248 ::close(mFd);
249 }
250
251 {
252 std::lock_guard<std::mutex> guard(mStateMutex);
253 mState = HalState::READY;
254 mH4 = nullptr;
255 }
256 }
257
clientDied()258 void BluetoothHci::clientDied() {
259 ALOGI(__func__);
260 close();
261 }
262
sendHciCommand(const std::vector<uint8_t> & packet)263 void BluetoothHci::sendHciCommand(const std::vector<uint8_t>& packet) {
264 return send(PacketType::COMMAND, packet);
265 }
266
sendAclData(const std::vector<uint8_t> & packet)267 void BluetoothHci::sendAclData(const std::vector<uint8_t>& packet) {
268 return send(PacketType::ACL_DATA, packet);
269 }
270
sendScoData(const std::vector<uint8_t> & packet)271 void BluetoothHci::sendScoData(const std::vector<uint8_t>& packet) {
272 return send(PacketType::SCO_DATA, packet);
273 }
274
sendIsoData(const std::vector<uint8_t> & packet)275 void BluetoothHci::sendIsoData(const std::vector<uint8_t>& packet) {
276 return send(PacketType::ISO_DATA, packet);
277 }
278
send(PacketType type,const std::vector<uint8_t> & v)279 void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
280 if (v.empty()) {
281 ALOGE("Packet is empty, no data was found to be sent");
282 abort();
283 }
284
285 std::lock_guard<std::mutex> guard(mStateMutex);
286 if (mH4 == nullptr) {
287 ALOGE("Illegal State");
288 abort();
289 }
290
291 mH4->Send(type, v);
292 }
293
294 } // namespace aidl::android::hardware::bluetooth::impl
295