• 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 // TODO: Remove custom logging defines from PDL packets.
33 #undef LOG_INFO
34 #undef LOG_DEBUG
35 #include "hci/hci_packets.h"
36 
37 namespace {
SetTerminalRaw(int fd)38 int 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 
50 using namespace ::android::hardware::bluetooth::hci;
51 using namespace ::android::hardware::bluetooth::async;
52 using aidl::android::hardware::bluetooth::Status;
53 
54 namespace aidl::android::hardware::bluetooth::impl {
55 
56 void OnDeath(void* cookie);
57 
58 class BluetoothDeathRecipient {
59  public:
BluetoothDeathRecipient(BluetoothHci * hci)60   BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
61 
LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks> & cb)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 
UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks> & cb)71   void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
72     LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
73   }
74 
serviceDied()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     }
82     {
83       std::lock_guard<std::mutex> guard(mHasDiedMutex);
84       has_died_ = true;
85     }
86     mHci->close();
87   }
88   BluetoothHci* mHci;
89   std::shared_ptr<IBluetoothHciCallbacks> mCb;
90   AIBinder_DeathRecipient* clientDeathRecipient_;
getHasDied()91   bool getHasDied() {
92     std::lock_guard<std::mutex> guard(mHasDiedMutex);
93     return has_died_;
94   }
95 
96  private:
97   std::mutex mHasDiedMutex;
98   bool has_died_{false};
99 };
100 
OnDeath(void * cookie)101 void OnDeath(void* cookie) {
102   auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
103   death_recipient->serviceDied();
104 }
105 
BluetoothHci(const std::string & dev_path)106 BluetoothHci::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 
getFdFromDevPath()113 int BluetoothHci::getFdFromDevPath() {
114   int fd = open(mDevPath.c_str(), O_RDWR);
115   if (fd < 0) {
116     ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
117           strerror(errno));
118     return fd;
119   }
120   if (int ret = SetTerminalRaw(fd) < 0) {
121     ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
122           strerror(errno));
123   }
124   return fd;
125 }
126 
reset()127 void 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 
177   send(PacketType::COMMAND, reset);
178   auto status = resetFuture.wait_for(std::chrono::seconds(1));
179   mFdWatcher.StopWatchingFileDescriptors();
180   if (status == std::future_status::ready) {
181     ALOGI("HCI Reset successful");
182   } else {
183     ALOGE("HCI Reset Response not received in one second");
184   }
185 
186   resetPromise.reset();
187 }
188 
initialize(const std::shared_ptr<IBluetoothHciCallbacks> & cb)189 ndk::ScopedAStatus BluetoothHci::initialize(
190     const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
191   ALOGI(__func__);
192 
193   if (cb == nullptr) {
194     ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
195     return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
196   }
197 
198   HalState old_state = HalState::READY;
199   {
200     std::lock_guard<std::mutex> guard(mStateMutex);
201     if (mState != HalState::READY) {
202       old_state = mState;
203     } else {
204       mState = HalState::INITIALIZING;
205     }
206   }
207 
208   if (old_state != HalState::READY) {
209     ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
210     close();
211     cb->initializationComplete(Status::ALREADY_INITIALIZED);
212     return ndk::ScopedAStatus::ok();
213   }
214 
215   mCb = cb;
216   management_.reset(new NetBluetoothMgmt);
217   mFd = management_->openHci();
218   if (mFd < 0) {
219     management_.reset();
220 
221     ALOGI("Unable to open Linux interface, trying default path.");
222     mFd = getFdFromDevPath();
223     if (mFd < 0) {
224       cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
225       return ndk::ScopedAStatus::ok();
226     }
227   }
228 
229   mDeathRecipient->LinkToDeath(mCb);
230 
231   // TODO: This should not be necessary when the device implements rfkill.
232   reset();
233 
234   mH4 = std::make_shared<H4Protocol>(
235       mFd,
236       [](const std::vector<uint8_t>& /* raw_command */) {
237         LOG_ALWAYS_FATAL("Unexpected command!");
238       },
239       [this](const std::vector<uint8_t>& raw_acl) {
240         mCb->aclDataReceived(raw_acl);
241       },
242       [this](const std::vector<uint8_t>& raw_sco) {
243         mCb->scoDataReceived(raw_sco);
244       },
245       [this](const std::vector<uint8_t>& raw_event) {
246         mCb->hciEventReceived(raw_event);
247       },
248       [this](const std::vector<uint8_t>& raw_iso) {
249         mCb->isoDataReceived(raw_iso);
250       },
251       [this]() {
252         ALOGI("HCI socket device disconnected");
253         mFdWatcher.StopWatchingFileDescriptors();
254       });
255   mFdWatcher.WatchFdForNonBlockingReads(mFd,
256                                         [this](int) { mH4->OnDataReady(); });
257 
258   {
259     std::lock_guard<std::mutex> guard(mStateMutex);
260     mState = HalState::ONE_CLIENT;
261   }
262   ALOGI("initialization complete");
263   auto status = mCb->initializationComplete(Status::SUCCESS);
264   if (!status.isOk()) {
265     if (!mDeathRecipient->getHasDied()) {
266       ALOGE("Error sending init callback, but no death notification");
267     }
268     close();
269     return ndk::ScopedAStatus::fromServiceSpecificError(
270         STATUS_FAILED_TRANSACTION);
271   }
272 
273   return ndk::ScopedAStatus::ok();
274 }
275 
close()276 ndk::ScopedAStatus BluetoothHci::close() {
277   ALOGI(__func__);
278   {
279     std::lock_guard<std::mutex> guard(mStateMutex);
280     if (mState != HalState::ONE_CLIENT) {
281       ALOGI("Already closed");
282       return ndk::ScopedAStatus::ok();
283     }
284     mState = HalState::CLOSING;
285   }
286 
287   mFdWatcher.StopWatchingFileDescriptors();
288 
289   if (management_) {
290     management_->closeHci();
291   } else {
292     ::close(mFd);
293   }
294 
295   {
296     std::lock_guard<std::mutex> guard(mStateMutex);
297     mState = HalState::READY;
298   }
299   return ndk::ScopedAStatus::ok();
300 }
301 
sendHciCommand(const std::vector<uint8_t> & packet)302 ndk::ScopedAStatus BluetoothHci::sendHciCommand(
303     const std::vector<uint8_t>& packet) {
304   send(PacketType::COMMAND, packet);
305   return ndk::ScopedAStatus::ok();
306 }
307 
sendAclData(const std::vector<uint8_t> & packet)308 ndk::ScopedAStatus BluetoothHci::sendAclData(
309     const std::vector<uint8_t>& packet) {
310   send(PacketType::ACL_DATA, packet);
311   return ndk::ScopedAStatus::ok();
312 }
313 
sendScoData(const std::vector<uint8_t> & packet)314 ndk::ScopedAStatus BluetoothHci::sendScoData(
315     const std::vector<uint8_t>& packet) {
316   send(PacketType::SCO_DATA, packet);
317   return ndk::ScopedAStatus::ok();
318 }
319 
sendIsoData(const std::vector<uint8_t> & packet)320 ndk::ScopedAStatus BluetoothHci::sendIsoData(
321     const std::vector<uint8_t>& packet) {
322   send(PacketType::ISO_DATA, packet);
323   return ndk::ScopedAStatus::ok();
324 }
325 
send(PacketType type,const std::vector<uint8_t> & v)326 void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
327   mH4->Send(type, v);
328 }
329 
330 }  // namespace aidl::android::hardware::bluetooth::impl
331