blob: eebbbc00d17fc2193d0ed648d049eae480d7c554 [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
32namespace {
33int 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
45using namespace ::android::hardware::bluetooth::hci;
46using namespace ::android::hardware::bluetooth::async;
Myles Watsonefa25d72022-10-03 16:27:32 -070047using aidl::android::hardware::bluetooth::Status;
Myles Watson6d5e7722022-09-30 06:22:43 -070048
49namespace aidl::android::hardware::bluetooth::impl {
50
51void OnDeath(void* cookie);
52
53class BluetoothDeathRecipient {
54 public:
55 BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
56
57 void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
58 mCb = cb;
59 clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
60 auto linkToDeathReturnStatus = AIBinder_linkToDeath(
61 mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
62 LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
63 "Unable to link to death recipient");
64 }
65
66 void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
67 LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
68 }
69
70 void serviceDied() {
71 if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
72 ALOGE("Bluetooth remote service has died");
73 } else {
74 ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
75 return;
76 }
77 has_died_ = true;
78 mHci->close();
79 }
80 BluetoothHci* mHci;
81 std::shared_ptr<IBluetoothHciCallbacks> mCb;
82 AIBinder_DeathRecipient* clientDeathRecipient_;
83 bool getHasDied() const { return has_died_; }
84
85 private:
Myles Watson8678c752022-11-03 10:41:44 -070086 bool has_died_{false};
Myles Watson6d5e7722022-09-30 06:22:43 -070087};
88
89void OnDeath(void* cookie) {
90 auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
91 death_recipient->serviceDied();
92}
93
94BluetoothHci::BluetoothHci(const std::string& dev_path) {
95 char property_bytes[PROPERTY_VALUE_MAX];
96 property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
97 mDevPath = std::string(property_bytes);
98 mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
99}
100
Myles Watsonefa25d72022-10-03 16:27:32 -0700101int BluetoothHci::getFdFromDevPath() {
102 int fd = open(mDevPath.c_str(), O_RDWR);
103 if (fd < 0) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700104 ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
105 strerror(errno));
Myles Watsonefa25d72022-10-03 16:27:32 -0700106 return fd;
Myles Watson6d5e7722022-09-30 06:22:43 -0700107 }
108 if (int ret = SetTerminalRaw(mFd) < 0) {
109 ALOGE("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
110 strerror(errno));
Myles Watsonefa25d72022-10-03 16:27:32 -0700111 ::close(fd);
112 return -1;
Myles Watson6d5e7722022-09-30 06:22:43 -0700113 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700114 return fd;
115}
116
117ndk::ScopedAStatus BluetoothHci::initialize(
118 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
119 ALOGI(__func__);
Myles Watson6d5e7722022-09-30 06:22:43 -0700120
121 mCb = cb;
122 if (mCb == nullptr) {
123 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
124 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
125 }
126
Myles Watsonefa25d72022-10-03 16:27:32 -0700127 management_.reset(new NetBluetoothMgmt);
128 mFd = management_->openHci();
129 if (mFd < 0) {
130 management_.reset();
131
132 ALOGI("Unable to open Linux interface, trying default path.");
133 mFd = getFdFromDevPath();
134 if (mFd < 0) {
135 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
136 }
137 }
138
Myles Watson6d5e7722022-09-30 06:22:43 -0700139 mDeathRecipient->LinkToDeath(mCb);
140
Myles Watson6d5e7722022-09-30 06:22:43 -0700141 mH4 = std::make_shared<H4Protocol>(
142 mFd,
143 [](const std::vector<uint8_t>& /* raw_command */) {
144 LOG_ALWAYS_FATAL("Unexpected command!");
145 },
David Duartea58b79d2023-01-19 18:14:32 +0000146 [this](const std::vector<uint8_t>& raw_acl) {
147 mCb->aclDataReceived(raw_acl);
148 },
149 [this](const std::vector<uint8_t>& raw_sco) {
150 mCb->scoDataReceived(raw_sco);
151 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700152 [this](const std::vector<uint8_t>& raw_event) {
153 mCb->hciEventReceived(raw_event);
154 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700155 [this](const std::vector<uint8_t>& raw_iso) {
David Duartea58b79d2023-01-19 18:14:32 +0000156 mCb->isoDataReceived(raw_iso);
Myles Watson6d5e7722022-09-30 06:22:43 -0700157 },
158 [this]() {
159 ALOGI("HCI socket device disconnected");
160 mFdWatcher.StopWatchingFileDescriptors();
161 });
162 mFdWatcher.WatchFdForNonBlockingReads(mFd,
163 [this](int) { mH4->OnDataReady(); });
Myles Watsonefa25d72022-10-03 16:27:32 -0700164
165 ALOGI("initialization complete");
166 auto status = mCb->initializationComplete(Status::SUCCESS);
167 if (!status.isOk()) {
168 if (!mDeathRecipient->getHasDied()) {
169 ALOGE("Error sending init callback, but no death notification");
170 }
171 close();
172 return ndk::ScopedAStatus::fromServiceSpecificError(
173 STATUS_FAILED_TRANSACTION);
174 }
175
Myles Watson6d5e7722022-09-30 06:22:43 -0700176 return ndk::ScopedAStatus::ok();
177}
178
179ndk::ScopedAStatus BluetoothHci::close() {
180 ALOGI(__func__);
181 mFdWatcher.StopWatchingFileDescriptors();
Myles Watsonefa25d72022-10-03 16:27:32 -0700182 if (management_) {
183 management_->closeHci();
184 } else {
185 ::close(mFd);
186 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700187
188 return ndk::ScopedAStatus::ok();
189}
190
191ndk::ScopedAStatus BluetoothHci::sendHciCommand(
192 const std::vector<uint8_t>& packet) {
193 send(PacketType::COMMAND, packet);
194 return ndk::ScopedAStatus::ok();
195}
196
197ndk::ScopedAStatus BluetoothHci::sendAclData(
198 const std::vector<uint8_t>& packet) {
199 send(PacketType::ACL_DATA, packet);
200 return ndk::ScopedAStatus::ok();
201}
202
203ndk::ScopedAStatus BluetoothHci::sendScoData(
204 const std::vector<uint8_t>& packet) {
205 send(PacketType::SCO_DATA, packet);
206 return ndk::ScopedAStatus::ok();
207}
208
209ndk::ScopedAStatus BluetoothHci::sendIsoData(
210 const std::vector<uint8_t>& packet) {
211 send(PacketType::ISO_DATA, packet);
212 return ndk::ScopedAStatus::ok();
213}
214
215void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
216 mH4->Send(type, v);
217}
218
219} // namespace aidl::android::hardware::bluetooth::impl