• 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 "metrics/counter_metrics.h"
34 #include "os/log.h"
35 #include "os/reactor.h"
36 #include "os/thread.h"
37 
38 namespace {
39 constexpr int INVALID_FD = -1;
40 
41 constexpr uint8_t kH4Command = 0x01;
42 constexpr uint8_t kH4Acl = 0x02;
43 constexpr uint8_t kH4Sco = 0x03;
44 constexpr uint8_t kH4Event = 0x04;
45 constexpr uint8_t kH4Iso = 0x05;
46 
47 constexpr uint8_t kH4HeaderSize = 1;
48 constexpr uint8_t kHciAclHeaderSize = 4;
49 constexpr uint8_t kHciScoHeaderSize = 3;
50 constexpr uint8_t kHciEvtHeaderSize = 2;
51 constexpr uint8_t kHciIsoHeaderSize = 4;
52 constexpr int kBufSize = 1024 + 4 + 1;  // DeviceProperties::acl_data_packet_size_ + ACL header + H4 header
53 
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 }
201 
202 namespace bluetooth {
203 namespace hal {
204 
205 class HciHalHost : public HciHal {
206  public:
registerIncomingPacketCallback(HciHalCallbacks * callback)207   void registerIncomingPacketCallback(HciHalCallbacks* callback) override {
208     std::lock_guard<std::mutex> lock(api_mutex_);
209     LOG_INFO("%s before", __func__);
210     {
211       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
212       ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr);
213       incoming_packet_callback_ = callback;
214     }
215     LOG_INFO("%s after", __func__);
216   }
217 
unregisterIncomingPacketCallback()218   void unregisterIncomingPacketCallback() override {
219     std::lock_guard<std::mutex> lock(api_mutex_);
220     LOG_INFO("%s before", __func__);
221     {
222       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
223       incoming_packet_callback_ = nullptr;
224     }
225     LOG_INFO("%s after", __func__);
226   }
227 
sendHciCommand(HciPacket command)228   void sendHciCommand(HciPacket command) override {
229     std::lock_guard<std::mutex> lock(api_mutex_);
230     ASSERT(sock_fd_ != INVALID_FD);
231     std::vector<uint8_t> packet = std::move(command);
232     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
233     packet.insert(packet.cbegin(), kH4Command);
234     write_to_fd(packet);
235   }
236 
sendAclData(HciPacket data)237   void sendAclData(HciPacket data) override {
238     std::lock_guard<std::mutex> lock(api_mutex_);
239     ASSERT(sock_fd_ != INVALID_FD);
240     std::vector<uint8_t> packet = std::move(data);
241     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
242     packet.insert(packet.cbegin(), kH4Acl);
243     write_to_fd(packet);
244   }
245 
sendScoData(HciPacket data)246   void sendScoData(HciPacket data) override {
247     std::lock_guard<std::mutex> lock(api_mutex_);
248     ASSERT(sock_fd_ != INVALID_FD);
249     std::vector<uint8_t> packet = std::move(data);
250     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::SCO);
251     packet.insert(packet.cbegin(), kH4Sco);
252     write_to_fd(packet);
253   }
254 
sendIsoData(HciPacket data)255   void sendIsoData(HciPacket data) override {
256     std::lock_guard<std::mutex> lock(api_mutex_);
257     ASSERT(sock_fd_ != INVALID_FD);
258     std::vector<uint8_t> packet = std::move(data);
259     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ISO);
260     packet.insert(packet.cbegin(), kH4Iso);
261     write_to_fd(packet);
262   }
263 
264  protected:
ListDependencies(ModuleList * list) const265   void ListDependencies(ModuleList* list) const {
266     list->add<metrics::CounterMetrics>();
267     list->add<SnoopLogger>();
268   }
269 
Start()270   void Start() override {
271     std::lock_guard<std::mutex> lock(api_mutex_);
272     ASSERT(sock_fd_ == INVALID_FD);
273     sock_fd_ = ConnectToSocket();
274     ASSERT(sock_fd_ != INVALID_FD);
275     reactable_ = hci_incoming_thread_.GetReactor()->Register(
276         sock_fd_, common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)), common::Closure());
277     btsnoop_logger_ = GetDependency<SnoopLogger>();
278     LOG_INFO("HAL opened successfully");
279   }
280 
Stop()281   void Stop() override {
282     std::lock_guard<std::mutex> lock(api_mutex_);
283     LOG_INFO("HAL is closing");
284     if (reactable_ != nullptr) {
285       hci_incoming_thread_.GetReactor()->Unregister(reactable_);
286       LOG_INFO("HAL is stopping, start waiting for last callback");
287       // Wait up to 1 second for the last incoming packet callback to finish
288       hci_incoming_thread_.GetReactor()->WaitForUnregisteredReactable(std::chrono::milliseconds(1000));
289       LOG_INFO("HAL is stopping, finished waiting for last callback");
290       ASSERT(sock_fd_ != INVALID_FD);
291     }
292     reactable_ = nullptr;
293     {
294       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
295       incoming_packet_callback_ = nullptr;
296     }
297     ::close(sock_fd_);
298     sock_fd_ = INVALID_FD;
299     LOG_INFO("HAL is closed");
300   }
301 
ToString() const302   std::string ToString() const override {
303     return std::string("HciHalHost");
304   }
305 
306  private:
307   // Held when APIs are called, NOT to be held during callbacks
308   std::mutex api_mutex_;
309   HciHalCallbacks* incoming_packet_callback_ = nullptr;
310   std::mutex incoming_packet_callback_mutex_;
311   int sock_fd_ = INVALID_FD;
312   bluetooth::os::Thread hci_incoming_thread_ =
313       bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL);
314   bluetooth::os::Reactor::Reactable* reactable_ = nullptr;
315   std::queue<std::vector<uint8_t>> hci_outgoing_queue_;
316   SnoopLogger* btsnoop_logger_ = nullptr;
317 
write_to_fd(HciPacket packet)318   void write_to_fd(HciPacket packet) {
319     // TODO: replace this with new queue when it's ready
320     hci_outgoing_queue_.emplace(packet);
321     if (hci_outgoing_queue_.size() == 1) {
322       hci_incoming_thread_.GetReactor()->ModifyRegistration(
323           reactable_,
324           common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)),
325           common::Bind(&HciHalHost::send_packet_ready, common::Unretained(this)));
326     }
327   }
328 
send_packet_ready()329   void send_packet_ready() {
330     std::lock_guard<std::mutex> lock(this->api_mutex_);
331     auto packet_to_send = this->hci_outgoing_queue_.front();
332     auto bytes_written = write(this->sock_fd_, (void*)packet_to_send.data(), packet_to_send.size());
333     this->hci_outgoing_queue_.pop();
334     if (bytes_written == -1) {
335       abort();
336     }
337     if (hci_outgoing_queue_.empty()) {
338       this->hci_incoming_thread_.GetReactor()->ModifyRegistration(
339           this->reactable_,
340           common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)),
341           common::Closure());
342     }
343   }
344 
incoming_packet_received()345   void incoming_packet_received() {
346     {
347       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
348       if (incoming_packet_callback_ == nullptr) {
349         LOG_INFO("Dropping a packet");
350         return;
351       }
352     }
353     uint8_t buf[kBufSize] = {};
354 
355     ssize_t received_size;
356     RUN_NO_INTR(received_size = read(sock_fd_, buf, kBufSize));
357     ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
358     if (received_size == 0) {
359       LOG_WARN("Can't read H4 header. EOF received");
360       raise(SIGINT);
361       return;
362     }
363 
364     if (buf[0] == kH4Event) {
365       ASSERT_LOG(
366           received_size >= kH4HeaderSize + kHciEvtHeaderSize, "Received bad HCI_EVT packet size: %zu", received_size);
367       uint8_t hci_evt_parameter_total_length = buf[2];
368       ssize_t payload_size = received_size - (kH4HeaderSize + kHciEvtHeaderSize);
369       ASSERT_LOG(
370           payload_size == hci_evt_parameter_total_length,
371           "malformed HCI event total parameter size received: %zu != %d",
372           payload_size,
373           hci_evt_parameter_total_length);
374 
375       HciPacket receivedHciPacket;
376       receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + payload_size);
377       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
378       {
379         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
380         if (incoming_packet_callback_ == nullptr) {
381           LOG_INFO("Dropping an event after processing");
382           return;
383         }
384         incoming_packet_callback_->hciEventReceived(receivedHciPacket);
385       }
386     }
387 
388     if (buf[0] == kH4Acl) {
389       ASSERT_LOG(
390           received_size >= kH4HeaderSize + kHciAclHeaderSize, "Received bad HCI_ACL packet size: %zu", received_size);
391       int payload_size = received_size - (kH4HeaderSize + kHciAclHeaderSize);
392       uint16_t hci_acl_data_total_length = (buf[4] << 8) + buf[3];
393       ASSERT_LOG(
394           payload_size == hci_acl_data_total_length,
395           "malformed ACL length received: %d != %d",
396           payload_size,
397           hci_acl_data_total_length);
398       ASSERT_LOG(hci_acl_data_total_length <= kBufSize - kH4HeaderSize - kHciAclHeaderSize, "packet too long");
399 
400       HciPacket receivedHciPacket;
401       receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + payload_size);
402       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
403       {
404         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
405         if (incoming_packet_callback_ == nullptr) {
406           LOG_INFO("Dropping an ACL packet after processing");
407           return;
408         }
409         incoming_packet_callback_->aclDataReceived(receivedHciPacket);
410       }
411     }
412 
413     if (buf[0] == kH4Sco) {
414       ASSERT_LOG(
415           received_size >= kH4HeaderSize + kHciScoHeaderSize, "Received bad HCI_SCO packet size: %zu", received_size);
416       int payload_size = received_size - (kH4HeaderSize + kHciScoHeaderSize);
417       uint8_t hci_sco_data_total_length = buf[3];
418       ASSERT_LOG(
419           payload_size == hci_sco_data_total_length,
420           "malformed SCO length received: %d != %d",
421           payload_size,
422           hci_sco_data_total_length);
423 
424       HciPacket receivedHciPacket;
425       receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + payload_size);
426       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::SCO);
427       {
428         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
429         if (incoming_packet_callback_ == nullptr) {
430           LOG_INFO("Dropping a SCO packet after processing");
431           return;
432         }
433         incoming_packet_callback_->scoDataReceived(receivedHciPacket);
434       }
435     }
436 
437     if (buf[0] == kH4Iso) {
438       ASSERT_LOG(
439           received_size >= kH4HeaderSize + kHciIsoHeaderSize, "Received bad HCI_ISO packet size: %zu", received_size);
440       int payload_size = received_size - (kH4HeaderSize + kHciIsoHeaderSize);
441       uint16_t hci_iso_data_total_length = ((buf[4] & 0x3f) << 8) + buf[3];
442       ASSERT_LOG(
443           payload_size == hci_iso_data_total_length,
444           "malformed ISO length received: %d != %d",
445           payload_size,
446           hci_iso_data_total_length);
447 
448       HciPacket receivedHciPacket;
449       receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciIsoHeaderSize + payload_size);
450       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ISO);
451       {
452         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
453         if (incoming_packet_callback_ == nullptr) {
454           LOG_INFO("Dropping a ISO packet after processing");
455           return;
456         }
457         incoming_packet_callback_->isoDataReceived(receivedHciPacket);
458       }
459     }
460     memset(buf, 0, kBufSize);
461   }
462 };
463 
__anon6f002e510202() 464 const ModuleFactory HciHal::Factory = ModuleFactory([]() { return new HciHalHost(); });
465 
466 }  // namespace hal
467 }  // namespace bluetooth
468