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