blob: d0ad4a3ffcef119f2f005f4a4a6d70f08f30a0d1 [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;
47
48namespace aidl::android::hardware::bluetooth::impl {
49
50void OnDeath(void* cookie);
51
52class BluetoothDeathRecipient {
53 public:
54 BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
55
56 void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
57 mCb = cb;
58 clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
59 auto linkToDeathReturnStatus = AIBinder_linkToDeath(
60 mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
61 LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
62 "Unable to link to death recipient");
63 }
64
65 void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
66 LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
67 }
68
69 void serviceDied() {
70 if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
71 ALOGE("Bluetooth remote service has died");
72 } else {
73 ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
74 return;
75 }
76 has_died_ = true;
77 mHci->close();
78 }
79 BluetoothHci* mHci;
80 std::shared_ptr<IBluetoothHciCallbacks> mCb;
81 AIBinder_DeathRecipient* clientDeathRecipient_;
82 bool getHasDied() const { return has_died_; }
83
84 private:
85 bool has_died_;
86};
87
88void OnDeath(void* cookie) {
89 auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
90 death_recipient->serviceDied();
91}
92
93BluetoothHci::BluetoothHci(const std::string& dev_path) {
94 char property_bytes[PROPERTY_VALUE_MAX];
95 property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
96 mDevPath = std::string(property_bytes);
97 mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
98}
99
100ndk::ScopedAStatus BluetoothHci::initialize(
101 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
102 ALOGI(__func__);
103
104 mFd = open(mDevPath.c_str(), O_RDWR);
105 if (mFd < 0) {
106 ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
107 strerror(errno));
108 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
109 }
110 if (int ret = SetTerminalRaw(mFd) < 0) {
111 ALOGE("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
112 strerror(errno));
113 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
114 }
115
116 mCb = cb;
117 if (mCb == nullptr) {
118 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
119 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
120 }
121
122 mDeathRecipient->LinkToDeath(mCb);
123
124 auto init_ret = cb->initializationComplete(Status::SUCCESS);
125 if (!init_ret.isOk()) {
126 if (!mDeathRecipient->getHasDied()) {
127 ALOGE("Error sending init callback, but no death notification.");
128 }
129 return ndk::ScopedAStatus::fromServiceSpecificError(
130 STATUS_FAILED_TRANSACTION);
131 }
132 mH4 = std::make_shared<H4Protocol>(
133 mFd,
134 [](const std::vector<uint8_t>& /* raw_command */) {
135 LOG_ALWAYS_FATAL("Unexpected command!");
136 },
137 [this](const std::vector<uint8_t>& raw_event) {
138 mCb->hciEventReceived(raw_event);
139 },
140 [this](const std::vector<uint8_t>& raw_acl) {
141 mCb->hciEventReceived(raw_acl);
142 },
143 [this](const std::vector<uint8_t>& raw_sco) {
144 mCb->hciEventReceived(raw_sco);
145 },
146 [this](const std::vector<uint8_t>& raw_iso) {
147 mCb->hciEventReceived(raw_iso);
148 },
149 [this]() {
150 ALOGI("HCI socket device disconnected");
151 mFdWatcher.StopWatchingFileDescriptors();
152 });
153 mFdWatcher.WatchFdForNonBlockingReads(mFd,
154 [this](int) { mH4->OnDataReady(); });
155 return ndk::ScopedAStatus::ok();
156}
157
158ndk::ScopedAStatus BluetoothHci::close() {
159 ALOGI(__func__);
160 mFdWatcher.StopWatchingFileDescriptors();
161 ::close(mFd);
162
163 return ndk::ScopedAStatus::ok();
164}
165
166ndk::ScopedAStatus BluetoothHci::sendHciCommand(
167 const std::vector<uint8_t>& packet) {
168 send(PacketType::COMMAND, packet);
169 return ndk::ScopedAStatus::ok();
170}
171
172ndk::ScopedAStatus BluetoothHci::sendAclData(
173 const std::vector<uint8_t>& packet) {
174 send(PacketType::ACL_DATA, packet);
175 return ndk::ScopedAStatus::ok();
176}
177
178ndk::ScopedAStatus BluetoothHci::sendScoData(
179 const std::vector<uint8_t>& packet) {
180 send(PacketType::SCO_DATA, packet);
181 return ndk::ScopedAStatus::ok();
182}
183
184ndk::ScopedAStatus BluetoothHci::sendIsoData(
185 const std::vector<uint8_t>& packet) {
186 send(PacketType::ISO_DATA, packet);
187 return ndk::ScopedAStatus::ok();
188}
189
190void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
191 mH4->Send(type, v);
192}
193
194} // namespace aidl::android::hardware::bluetooth::impl