1 /*
2 * Copyright 2019 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 #include <bluetooth/log.h>
18 #include <netdb.h>
19 #include <netinet/in.h>
20 #include <poll.h>
21 #include <sys/socket.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include <chrono>
26 #include <csignal>
27 #include <mutex>
28 #include <queue>
29
30 #include "hal/hci_hal.h"
31 #include "hal/hci_hal_host.h"
32 #include "hal/snoop_logger.h"
33 #include "metrics/counter_metrics.h"
34 #include "os/reactor.h"
35 #include "os/thread.h"
36
37 namespace {
38 constexpr int INVALID_FD = -1;
39
40 constexpr uint8_t kH4Command = 0x01;
41 constexpr uint8_t kH4Acl = 0x02;
42 constexpr uint8_t kH4Sco = 0x03;
43 constexpr uint8_t kH4Event = 0x04;
44 constexpr uint8_t kH4Iso = 0x05;
45
46 constexpr uint8_t kH4HeaderSize = 1;
47 constexpr uint8_t kHciAclHeaderSize = 4;
48 constexpr uint8_t kHciScoHeaderSize = 3;
49 constexpr uint8_t kHciEvtHeaderSize = 2;
50 constexpr uint8_t kHciIsoHeaderSize = 4;
51 constexpr int kBufSize =
52 1024 + 4 + 1; // DeviceProperties::acl_data_packet_size_ + ACL header + H4 header
53
ConnectToSocket()54 int ConnectToSocket() {
55 auto* config = bluetooth::hal::HciHalHostRootcanalConfig::Get();
56 const std::string& server = config->GetServerAddress();
57 int port = config->GetPort();
58
59 int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
60 if (socket_fd < 1) {
61 bluetooth::log::error("can't create socket: {}", strerror(errno));
62 return INVALID_FD;
63 }
64
65 struct hostent* host;
66 host = gethostbyname(server.c_str());
67 if (host == nullptr) {
68 bluetooth::log::error("can't get server name");
69 return INVALID_FD;
70 }
71
72 struct sockaddr_in serv_addr;
73 memset((void*)&serv_addr, 0, sizeof(serv_addr));
74 serv_addr.sin_family = AF_INET;
75 serv_addr.sin_addr.s_addr = INADDR_ANY;
76 serv_addr.sin_port = htons(port);
77
78 int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
79 if (result < 0) {
80 bluetooth::log::error("can't connect: {}", strerror(errno));
81 return INVALID_FD;
82 }
83
84 timeval socket_timeout{
85 .tv_sec = 3,
86 .tv_usec = 0,
87 };
88 int ret = setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
89 if (ret == -1) {
90 bluetooth::log::error("can't control socket fd: {}", strerror(errno));
91 return INVALID_FD;
92 }
93 return socket_fd;
94 }
95 } // namespace
96
97 namespace bluetooth {
98 namespace hal {
99
100 class HciHalHost : public HciHal {
101 public:
registerIncomingPacketCallback(HciHalCallbacks * callback)102 void registerIncomingPacketCallback(HciHalCallbacks* callback) override {
103 std::lock_guard<std::mutex> lock(api_mutex_);
104 log::info("before");
105 {
106 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
107 log::assert_that(
108 incoming_packet_callback_ == nullptr && callback != nullptr,
109 "assert failed: incoming_packet_callback_ == nullptr && callback != nullptr");
110 incoming_packet_callback_ = callback;
111 }
112 log::info("after");
113 }
114
unregisterIncomingPacketCallback()115 void unregisterIncomingPacketCallback() override {
116 std::lock_guard<std::mutex> lock(api_mutex_);
117 log::info("before");
118 {
119 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
120 incoming_packet_callback_ = nullptr;
121 }
122 log::info("after");
123 }
124
sendHciCommand(HciPacket command)125 void sendHciCommand(HciPacket command) override {
126 std::lock_guard<std::mutex> lock(api_mutex_);
127 log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
128 std::vector<uint8_t> packet = std::move(command);
129 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
130 SnoopLogger::PacketType::CMD);
131 packet.insert(packet.cbegin(), kH4Command);
132 write_to_fd(packet);
133 }
134
sendAclData(HciPacket data)135 void sendAclData(HciPacket data) override {
136 std::lock_guard<std::mutex> lock(api_mutex_);
137 log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
138 std::vector<uint8_t> packet = std::move(data);
139 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
140 SnoopLogger::PacketType::ACL);
141 packet.insert(packet.cbegin(), kH4Acl);
142 write_to_fd(packet);
143 }
144
sendScoData(HciPacket data)145 void sendScoData(HciPacket data) override {
146 std::lock_guard<std::mutex> lock(api_mutex_);
147 log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
148 std::vector<uint8_t> packet = std::move(data);
149 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
150 SnoopLogger::PacketType::SCO);
151 packet.insert(packet.cbegin(), kH4Sco);
152 write_to_fd(packet);
153 }
154
sendIsoData(HciPacket data)155 void sendIsoData(HciPacket data) override {
156 std::lock_guard<std::mutex> lock(api_mutex_);
157 log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
158 std::vector<uint8_t> packet = std::move(data);
159 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
160 SnoopLogger::PacketType::ISO);
161 packet.insert(packet.cbegin(), kH4Iso);
162 write_to_fd(packet);
163 }
164
165 protected:
ListDependencies(ModuleList * list) const166 void ListDependencies(ModuleList* list) const {
167 list->add<metrics::CounterMetrics>();
168 list->add<SnoopLogger>();
169 }
170
Start()171 void Start() override {
172 std::lock_guard<std::mutex> lock(api_mutex_);
173 log::assert_that(sock_fd_ == INVALID_FD, "assert failed: sock_fd_ == INVALID_FD");
174 sock_fd_ = ConnectToSocket();
175 log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
176 reactable_ = hci_incoming_thread_.GetReactor()->Register(
177 sock_fd_, common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)),
178 common::Bind(&HciHalHost::send_packet_ready, common::Unretained(this)));
179 hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_,
180 os::Reactor::REACT_ON_READ_ONLY);
181 btsnoop_logger_ = GetDependency<SnoopLogger>();
182 log::info("HAL opened successfully");
183 }
184
Stop()185 void Stop() override {
186 std::lock_guard<std::mutex> lock(api_mutex_);
187 log::info("HAL is closing");
188 if (reactable_ != nullptr) {
189 hci_incoming_thread_.GetReactor()->Unregister(reactable_);
190 log::info("HAL is stopping, start waiting for last callback");
191 // Wait up to 1 second for the last incoming packet callback to finish
192 hci_incoming_thread_.GetReactor()->WaitForUnregisteredReactable(
193 std::chrono::milliseconds(1000));
194 log::info("HAL is stopping, finished waiting for last callback");
195 log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
196 }
197 reactable_ = nullptr;
198 {
199 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
200 incoming_packet_callback_ = nullptr;
201 }
202 ::close(sock_fd_);
203 sock_fd_ = INVALID_FD;
204 log::info("HAL is closed");
205 }
206
ToString() const207 std::string ToString() const override { return std::string("HciHalHost"); }
208
209 private:
210 // Held when APIs are called, NOT to be held during callbacks
211 std::mutex api_mutex_;
212 HciHalCallbacks* incoming_packet_callback_ = nullptr;
213 std::mutex incoming_packet_callback_mutex_;
214 int sock_fd_ = INVALID_FD;
215 bluetooth::os::Thread hci_incoming_thread_ =
216 bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL);
217 bluetooth::os::Reactor::Reactable* reactable_ = nullptr;
218 std::queue<std::vector<uint8_t>> hci_outgoing_queue_;
219 SnoopLogger* btsnoop_logger_ = nullptr;
220
write_to_fd(HciPacket packet)221 void write_to_fd(HciPacket packet) {
222 // TODO: replace this with new queue when it's ready
223 hci_outgoing_queue_.emplace(packet);
224 if (hci_outgoing_queue_.size() == 1) {
225 hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_,
226 os::Reactor::REACT_ON_READ_WRITE);
227 }
228 }
229
send_packet_ready()230 void send_packet_ready() {
231 std::lock_guard<std::mutex> lock(api_mutex_);
232 if (hci_outgoing_queue_.empty()) {
233 return;
234 }
235 auto packet_to_send = hci_outgoing_queue_.front();
236 auto bytes_written = write(sock_fd_, (void*)packet_to_send.data(), packet_to_send.size());
237 hci_outgoing_queue_.pop();
238 if (bytes_written == -1) {
239 abort();
240 }
241 if (hci_outgoing_queue_.empty()) {
242 hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_,
243 os::Reactor::REACT_ON_READ_ONLY);
244 }
245 }
246
socketRecvAll(void * buffer,int bufferLen)247 bool socketRecvAll(void* buffer, int bufferLen) {
248 auto buf = static_cast<char*>(buffer);
249 while (bufferLen > 0) {
250 ssize_t ret;
251 RUN_NO_INTR(ret = recv(sock_fd_, buf, bufferLen, 0));
252 if (ret <= 0) {
253 return false;
254 }
255 buf += ret;
256 bufferLen -= ret;
257 }
258 return true;
259 }
260
incoming_packet_received()261 void incoming_packet_received() {
262 {
263 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
264 if (incoming_packet_callback_ == nullptr) {
265 log::info("Dropping a packet");
266 return;
267 }
268 }
269 uint8_t buf[kBufSize] = {};
270
271 ssize_t received_size;
272 RUN_NO_INTR(received_size = recv(sock_fd_, buf, kH4HeaderSize, 0));
273 log::assert_that(received_size != -1, "Can't receive from socket: {}", strerror(errno));
274 if (received_size == 0) {
275 log::warn("Can't read H4 header. EOF received");
276 raise(SIGINT);
277 return;
278 }
279
280 if (buf[0] == kH4Event) {
281 log::assert_that(socketRecvAll(buf + kH4HeaderSize, kHciEvtHeaderSize),
282 "Can't receive from socket: {}", strerror(errno));
283
284 uint8_t hci_evt_parameter_total_length = buf[2];
285 log::assert_that(socketRecvAll(buf + kH4HeaderSize + kHciEvtHeaderSize,
286 hci_evt_parameter_total_length),
287 "Can't receive from socket: {}", strerror(errno));
288
289 HciPacket receivedHciPacket;
290 receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize +
291 hci_evt_parameter_total_length);
292 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING,
293 SnoopLogger::PacketType::EVT);
294 {
295 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
296 if (incoming_packet_callback_ == nullptr) {
297 log::info("Dropping an event after processing");
298 return;
299 }
300 incoming_packet_callback_->hciEventReceived(receivedHciPacket);
301 }
302 }
303
304 if (buf[0] == kH4Acl) {
305 log::assert_that(socketRecvAll(buf + kH4HeaderSize, kHciAclHeaderSize),
306 "Can't receive from socket: {}", strerror(errno));
307
308 uint16_t hci_acl_data_total_length = (buf[4] << 8) + buf[3];
309 log::assert_that(
310 socketRecvAll(buf + kH4HeaderSize + kHciAclHeaderSize, hci_acl_data_total_length),
311 "Can't receive from socket: {}", strerror(errno));
312
313 HciPacket receivedHciPacket;
314 receivedHciPacket.assign(buf + kH4HeaderSize,
315 buf + kH4HeaderSize + kHciAclHeaderSize + hci_acl_data_total_length);
316 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING,
317 SnoopLogger::PacketType::ACL);
318 {
319 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
320 if (incoming_packet_callback_ == nullptr) {
321 log::info("Dropping an ACL packet after processing");
322 return;
323 }
324 incoming_packet_callback_->aclDataReceived(receivedHciPacket);
325 }
326 }
327
328 if (buf[0] == kH4Sco) {
329 log::assert_that(socketRecvAll(buf + kH4HeaderSize, kHciScoHeaderSize),
330 "Can't receive from socket: {}", strerror(errno));
331
332 uint8_t hci_sco_data_total_length = buf[3];
333 log::assert_that(
334 socketRecvAll(buf + kH4HeaderSize + kHciScoHeaderSize, hci_sco_data_total_length),
335 "Can't receive from socket: {}", strerror(errno));
336
337 HciPacket receivedHciPacket;
338 receivedHciPacket.assign(buf + kH4HeaderSize,
339 buf + kH4HeaderSize + kHciScoHeaderSize + hci_sco_data_total_length);
340 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING,
341 SnoopLogger::PacketType::SCO);
342 {
343 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
344 if (incoming_packet_callback_ == nullptr) {
345 log::info("Dropping a SCO packet after processing");
346 return;
347 }
348 incoming_packet_callback_->scoDataReceived(receivedHciPacket);
349 }
350 }
351
352 if (buf[0] == kH4Iso) {
353 log::assert_that(socketRecvAll(buf + kH4HeaderSize, kHciIsoHeaderSize),
354 "Can't receive from socket: {}", strerror(errno));
355
356 uint16_t hci_iso_data_total_length = ((buf[4] & 0x3f) << 8) + buf[3];
357 log::assert_that(
358 socketRecvAll(buf + kH4HeaderSize + kHciIsoHeaderSize, hci_iso_data_total_length),
359 "Can't receive from socket: {}", strerror(errno));
360
361 HciPacket receivedHciPacket;
362 receivedHciPacket.assign(buf + kH4HeaderSize,
363 buf + kH4HeaderSize + kHciIsoHeaderSize + hci_iso_data_total_length);
364 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING,
365 SnoopLogger::PacketType::ISO);
366 {
367 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
368 if (incoming_packet_callback_ == nullptr) {
369 log::info("Dropping a ISO packet after processing");
370 return;
371 }
372 incoming_packet_callback_->isoDataReceived(receivedHciPacket);
373 }
374 }
375 memset(buf, 0, kBufSize);
376 }
377 };
378
__anon7e758d3d0202() 379 const ModuleFactory HciHal::Factory = ModuleFactory([]() { return new HciHalHost(); });
380
381 } // namespace hal
382 } // namespace bluetooth
383