• 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 "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