• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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