• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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