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 "hal/hci_hal_host.h"
18
19 #include <netdb.h>
20 #include <netinet/in.h>
21 #include <poll.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #include <chrono>
27 #include <csignal>
28 #include <mutex>
29 #include <queue>
30
31 #include "gd/common/init_flags.h"
32 #include "hal/hci_hal.h"
33 #include "hal/mgmt.h"
34 #include "hal/snoop_logger.h"
35 #include "metrics/counter_metrics.h"
36 #include "os/log.h"
37 #include "os/reactor.h"
38 #include "os/thread.h"
39
40 namespace {
41 constexpr int INVALID_FD = -1;
42
43 constexpr uint8_t kH4Command = 0x01;
44 constexpr uint8_t kH4Acl = 0x02;
45 constexpr uint8_t kH4Sco = 0x03;
46 constexpr uint8_t kH4Event = 0x04;
47 constexpr uint8_t kH4Iso = 0x05;
48
49 constexpr uint8_t kH4HeaderSize = 1;
50 constexpr uint8_t kHciAclHeaderSize = 4;
51 constexpr uint8_t kHciScoHeaderSize = 3;
52 constexpr uint8_t kHciEvtHeaderSize = 2;
53 constexpr uint8_t kHciIsoHeaderSize = 4;
54 constexpr int kBufSize = 1024 + 4 + 1; // DeviceProperties::acl_data_packet_size_ + ACL header + H4 header
55
56 constexpr uint8_t BTPROTO_HCI = 1;
57 constexpr uint16_t HCI_CHANNEL_USER = 1;
58 constexpr uint16_t HCI_CHANNEL_CONTROL = 3;
59 constexpr uint16_t HCI_DEV_NONE = 0xffff;
60
61 /* reference from <kernel>/include/net/bluetooth/mgmt.h */
62 #define MGMT_OP_INDEX_LIST 0x0003
63 #define MGMT_EV_INDEX_ADDED 0x0004
64 #define MGMT_EV_COMMAND_COMP 0x0001
65 #define MGMT_EV_SIZE_MAX 1024
66 #define REPEAT_ON_INTR(fn) \
67 do { \
68 } while ((fn) == -1 && errno == EINTR)
69
70 struct sockaddr_hci {
71 sa_family_t hci_family;
72 unsigned short hci_dev;
73 unsigned short hci_channel;
74 };
75
76 struct mgmt_pkt {
77 uint16_t opcode;
78 uint16_t index;
79 uint16_t len;
80 uint8_t data[MGMT_EV_SIZE_MAX];
81 } __attribute__((packed));
82
83 struct mgmt_event_read_index {
84 uint16_t cc_opcode;
85 uint8_t status;
86 uint16_t num_intf;
87 uint16_t index[0];
88 } __attribute__((packed));
89
waitHciDev(int hci_interface)90 int waitHciDev(int hci_interface) {
91 struct sockaddr_hci addr;
92 struct pollfd fds[1];
93 struct mgmt_pkt ev;
94 int fd;
95 int ret;
96
97 fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
98 if (fd < 0) {
99 LOG_ERROR("Bluetooth socket error: %s", strerror(errno));
100 return -1;
101 }
102 memset(&addr, 0, sizeof(addr));
103 addr.hci_family = AF_BLUETOOTH;
104 addr.hci_dev = HCI_DEV_NONE;
105 addr.hci_channel = HCI_CHANNEL_CONTROL;
106
107 ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
108 if (ret < 0) {
109 LOG_ERROR("HCI Channel Control: %d %s", errno, strerror(errno));
110 close(fd);
111 return -1;
112 }
113
114 fds[0].fd = fd;
115 fds[0].events = POLLIN;
116
117 /* Read Controller Index List Command */
118 ev.opcode = MGMT_OP_INDEX_LIST;
119 ev.index = HCI_DEV_NONE;
120 ev.len = 0;
121
122 ssize_t wrote;
123 REPEAT_ON_INTR(wrote = write(fd, &ev, 6));
124 if (wrote != 6) {
125 LOG_ERROR("Unable to write mgmt command: %s", strerror(errno));
126 close(fd);
127 return -1;
128 }
129 /* validate mentioned hci interface is present and registered with sock system */
130 while (1) {
131 int n;
132 REPEAT_ON_INTR(n = poll(fds, 1, -1));
133 if (n == -1) {
134 LOG_ERROR("Poll error: %s", strerror(errno));
135 break;
136 } else if (n == 0) {
137 LOG_ERROR("Timeout, no HCI device detected");
138 break;
139 }
140
141 if (fds[0].revents & POLLIN) {
142 REPEAT_ON_INTR(n = read(fd, &ev, sizeof(struct mgmt_pkt)));
143 if (n < 0) {
144 LOG_ERROR("Error reading control channel: %s", strerror(errno));
145 break;
146 }
147
148 if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
149 close(fd);
150 return -1;
151 } else if (ev.opcode == MGMT_EV_COMMAND_COMP) {
152 struct mgmt_event_read_index* cc;
153 int i;
154
155 cc = (struct mgmt_event_read_index*)ev.data;
156
157 if (cc->cc_opcode != MGMT_OP_INDEX_LIST || cc->status != 0) continue;
158
159 for (i = 0; i < cc->num_intf; i++) {
160 if (cc->index[i] == hci_interface) {
161 close(fd);
162 return 0;
163 }
164 }
165 }
166 }
167 }
168
169 close(fd);
170 return -1;
171 }
172
173 // Connect to Linux HCI socket
ConnectToSocket()174 int ConnectToSocket() {
175 int ret = 0;
176
177 int socket_fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
178 if (socket_fd < 0) {
179 LOG_ERROR("can't create socket: %s", strerror(errno));
180 return INVALID_FD;
181 }
182
183 // Determine which hci index we should connect to.
184 int hci_interface = bluetooth::common::InitFlags::GetAdapterIndex();
185
186 if (waitHciDev(hci_interface) != 0) {
187 ::close(socket_fd);
188 return INVALID_FD;
189 }
190
191 struct sockaddr_hci addr;
192 memset(&addr, 0, sizeof(addr));
193 addr.hci_family = AF_BLUETOOTH;
194 addr.hci_dev = hci_interface;
195 addr.hci_channel = HCI_CHANNEL_USER;
196
197 ret = bind(socket_fd, (struct sockaddr*)&addr, sizeof(addr));
198 if (ret < 0) {
199 LOG_ERROR("HCI Channel Control: %d %s", errno, strerror(errno));
200 ::close(socket_fd);
201 return INVALID_FD;
202 }
203 LOG_INFO("HCI device ready");
204 return socket_fd;
205 }
206 }
207
208 namespace bluetooth {
209 namespace hal {
210
211 class HciHalHost : public HciHal {
212 public:
registerIncomingPacketCallback(HciHalCallbacks * callback)213 void registerIncomingPacketCallback(HciHalCallbacks* callback) override {
214 std::lock_guard<std::mutex> lock(api_mutex_);
215 LOG_INFO("%s before", __func__);
216 {
217 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
218 ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr);
219 incoming_packet_callback_ = callback;
220 }
221 LOG_INFO("%s after", __func__);
222 }
223
unregisterIncomingPacketCallback()224 void unregisterIncomingPacketCallback() override {
225 std::lock_guard<std::mutex> lock(api_mutex_);
226 LOG_INFO("%s before", __func__);
227 {
228 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
229 incoming_packet_callback_ = nullptr;
230 }
231 LOG_INFO("%s after", __func__);
232 }
233
sendHciCommand(HciPacket command)234 void sendHciCommand(HciPacket command) override {
235 std::lock_guard<std::mutex> lock(api_mutex_);
236 ASSERT(sock_fd_ != INVALID_FD);
237 std::vector<uint8_t> packet = std::move(command);
238 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
239 packet.insert(packet.cbegin(), kH4Command);
240 write_to_fd(packet);
241 }
242
sendAclData(HciPacket data)243 void sendAclData(HciPacket data) override {
244 std::lock_guard<std::mutex> lock(api_mutex_);
245 ASSERT(sock_fd_ != INVALID_FD);
246 std::vector<uint8_t> packet = std::move(data);
247 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
248 packet.insert(packet.cbegin(), kH4Acl);
249 write_to_fd(packet);
250 }
251
sendScoData(HciPacket data)252 void sendScoData(HciPacket data) override {
253 std::lock_guard<std::mutex> lock(api_mutex_);
254 ASSERT(sock_fd_ != INVALID_FD);
255 std::vector<uint8_t> packet = std::move(data);
256 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::SCO);
257 packet.insert(packet.cbegin(), kH4Sco);
258 write_to_fd(packet);
259 }
260
sendIsoData(HciPacket data)261 void sendIsoData(HciPacket data) override {
262 std::lock_guard<std::mutex> lock(api_mutex_);
263 ASSERT(sock_fd_ != INVALID_FD);
264 std::vector<uint8_t> packet = std::move(data);
265 btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ISO);
266 packet.insert(packet.cbegin(), kH4Iso);
267 write_to_fd(packet);
268 }
269
getMsftOpcode()270 uint16_t getMsftOpcode() override {
271 return Mgmt().get_vs_opcode(MGMT_VS_OPCODE_MSFT);
272 }
273
274 protected:
ListDependencies(ModuleList * list) const275 void ListDependencies(ModuleList* list) const {
276 list->add<metrics::CounterMetrics>();
277 list->add<SnoopLogger>();
278 }
279
Start()280 void Start() override {
281 std::lock_guard<std::mutex> lock(api_mutex_);
282 ASSERT(sock_fd_ == INVALID_FD);
283 sock_fd_ = ConnectToSocket();
284 ASSERT(sock_fd_ != INVALID_FD);
285 reactable_ = hci_incoming_thread_.GetReactor()->Register(
286 sock_fd_,
287 common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)),
288 common::Bind(&HciHalHost::send_packet_ready, common::Unretained(this)));
289 hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, os::Reactor::REACT_ON_READ_ONLY);
290 btsnoop_logger_ = GetDependency<SnoopLogger>();
291 LOG_INFO("HAL opened successfully");
292 }
293
Stop()294 void Stop() override {
295 std::lock_guard<std::mutex> lock(api_mutex_);
296 LOG_INFO("HAL is closing");
297 if (reactable_ != nullptr) {
298 hci_incoming_thread_.GetReactor()->Unregister(reactable_);
299 LOG_INFO("HAL is stopping, start waiting for last callback");
300 // Wait up to 1 second for the last incoming packet callback to finish
301 hci_incoming_thread_.GetReactor()->WaitForUnregisteredReactable(std::chrono::milliseconds(1000));
302 LOG_INFO("HAL is stopping, finished waiting for last callback");
303 ASSERT(sock_fd_ != INVALID_FD);
304 }
305 reactable_ = nullptr;
306 {
307 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
308 incoming_packet_callback_ = nullptr;
309 }
310 ::close(sock_fd_);
311 sock_fd_ = INVALID_FD;
312 LOG_INFO("HAL is closed");
313 }
314
ToString() const315 std::string ToString() const override {
316 return std::string("HciHalHost");
317 }
318
319 private:
320 // Held when APIs are called, NOT to be held during callbacks
321 std::mutex api_mutex_;
322 HciHalCallbacks* incoming_packet_callback_ = nullptr;
323 std::mutex incoming_packet_callback_mutex_;
324 int sock_fd_ = INVALID_FD;
325 bluetooth::os::Thread hci_incoming_thread_ =
326 bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL);
327 bluetooth::os::Reactor::Reactable* reactable_ = nullptr;
328 std::queue<std::vector<uint8_t>> hci_outgoing_queue_;
329 SnoopLogger* btsnoop_logger_ = nullptr;
330
write_to_fd(HciPacket packet)331 void write_to_fd(HciPacket packet) {
332 // TODO: replace this with new queue when it's ready
333 hci_outgoing_queue_.emplace(packet);
334 if (hci_outgoing_queue_.size() == 1) {
335 hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, os::Reactor::REACT_ON_READ_WRITE);
336 }
337 }
338
send_packet_ready()339 void send_packet_ready() {
340 std::lock_guard<std::mutex> lock(api_mutex_);
341 if (hci_outgoing_queue_.empty()) return;
342 auto packet_to_send = hci_outgoing_queue_.front();
343 auto bytes_written = write(sock_fd_, (void*)packet_to_send.data(), packet_to_send.size());
344 hci_outgoing_queue_.pop();
345 if (bytes_written == -1) {
346 abort();
347 }
348 if (hci_outgoing_queue_.empty()) {
349 hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, os::Reactor::REACT_ON_READ_ONLY);
350 }
351 }
352
incoming_packet_received()353 void incoming_packet_received() {
354 {
355 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
356 if (incoming_packet_callback_ == nullptr) {
357 LOG_INFO("Dropping a packet");
358 return;
359 }
360 }
361 uint8_t buf[kBufSize] = {};
362
363 ssize_t received_size;
364 RUN_NO_INTR(received_size = read(sock_fd_, buf, kBufSize));
365 ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
366 if (received_size == 0) {
367 LOG_WARN("Can't read H4 header. EOF received");
368 // First close sock fd before raising sigint
369 close(sock_fd_);
370 raise(SIGINT);
371 return;
372 }
373
374 if (buf[0] == kH4Event) {
375 ASSERT_LOG(
376 received_size >= kH4HeaderSize + kHciEvtHeaderSize, "Received bad HCI_EVT packet size: %zu", received_size);
377 uint8_t hci_evt_parameter_total_length = buf[2];
378 ssize_t payload_size = received_size - (kH4HeaderSize + kHciEvtHeaderSize);
379 ASSERT_LOG(
380 payload_size == hci_evt_parameter_total_length,
381 "malformed HCI event total parameter size received: %zu != %d",
382 payload_size,
383 hci_evt_parameter_total_length);
384
385 HciPacket receivedHciPacket;
386 receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + payload_size);
387 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
388 {
389 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
390 if (incoming_packet_callback_ == nullptr) {
391 LOG_INFO("Dropping an event after processing");
392 return;
393 }
394 incoming_packet_callback_->hciEventReceived(receivedHciPacket);
395 }
396 }
397
398 if (buf[0] == kH4Acl) {
399 ASSERT_LOG(
400 received_size >= kH4HeaderSize + kHciAclHeaderSize, "Received bad HCI_ACL packet size: %zu", received_size);
401 int payload_size = received_size - (kH4HeaderSize + kHciAclHeaderSize);
402 uint16_t hci_acl_data_total_length = (buf[4] << 8) + buf[3];
403 ASSERT_LOG(
404 payload_size == hci_acl_data_total_length,
405 "malformed ACL length received: %d != %d",
406 payload_size,
407 hci_acl_data_total_length);
408 ASSERT_LOG(hci_acl_data_total_length <= kBufSize - kH4HeaderSize - kHciAclHeaderSize, "packet too long");
409
410 HciPacket receivedHciPacket;
411 receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + payload_size);
412 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
413 {
414 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
415 if (incoming_packet_callback_ == nullptr) {
416 LOG_INFO("Dropping an ACL packet after processing");
417 return;
418 }
419 incoming_packet_callback_->aclDataReceived(receivedHciPacket);
420 }
421 }
422
423 if (buf[0] == kH4Sco) {
424 ASSERT_LOG(
425 received_size >= kH4HeaderSize + kHciScoHeaderSize, "Received bad HCI_SCO packet size: %zu", received_size);
426 int payload_size = received_size - (kH4HeaderSize + kHciScoHeaderSize);
427 uint8_t hci_sco_data_total_length = buf[3];
428 ASSERT_LOG(
429 payload_size == hci_sco_data_total_length,
430 "malformed SCO length received: %d != %d",
431 payload_size,
432 hci_sco_data_total_length);
433
434 HciPacket receivedHciPacket;
435 receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + payload_size);
436 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::SCO);
437 {
438 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
439 if (incoming_packet_callback_ == nullptr) {
440 LOG_INFO("Dropping a SCO packet after processing");
441 return;
442 }
443 incoming_packet_callback_->scoDataReceived(receivedHciPacket);
444 }
445 }
446
447 if (buf[0] == kH4Iso) {
448 ASSERT_LOG(
449 received_size >= kH4HeaderSize + kHciIsoHeaderSize, "Received bad HCI_ISO packet size: %zu", received_size);
450 int payload_size = received_size - (kH4HeaderSize + kHciIsoHeaderSize);
451 uint16_t hci_iso_data_total_length = ((buf[4] & 0x3f) << 8) + buf[3];
452 ASSERT_LOG(
453 payload_size == hci_iso_data_total_length,
454 "malformed ISO length received: %d != %d",
455 payload_size,
456 hci_iso_data_total_length);
457
458 HciPacket receivedHciPacket;
459 receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciIsoHeaderSize + payload_size);
460 btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ISO);
461 {
462 std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
463 if (incoming_packet_callback_ == nullptr) {
464 LOG_INFO("Dropping a ISO packet after processing");
465 return;
466 }
467 incoming_packet_callback_->isoDataReceived(receivedHciPacket);
468 }
469 }
470 memset(buf, 0, kBufSize);
471 }
472 };
473
__anonfd3fa4aa0202() 474 const ModuleFactory HciHal::Factory = ModuleFactory([]() { return new HciHalHost(); });
475
476 } // namespace hal
477 } // namespace bluetooth
478