• 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 
ConnectToSocket()54 int ConnectToSocket() {
55   auto* config = bluetooth::hal::HciHalHostRootcanalConfig::Get();
56   const std::string& server = config->GetServerAddress();
57   int port = config->GetPort();
58 
59   int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
60   if (socket_fd < 1) {
61     LOG_ERROR("can't create socket: %s", strerror(errno));
62     return INVALID_FD;
63   }
64 
65   struct hostent* host;
66   host = gethostbyname(server.c_str());
67   if (host == nullptr) {
68     LOG_ERROR("can't get server name");
69     return INVALID_FD;
70   }
71 
72   struct sockaddr_in serv_addr;
73   memset((void*)&serv_addr, 0, sizeof(serv_addr));
74   serv_addr.sin_family = AF_INET;
75   serv_addr.sin_addr.s_addr = INADDR_ANY;
76   serv_addr.sin_port = htons(port);
77 
78   int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
79   if (result < 0) {
80     LOG_ERROR("can't connect: %s", strerror(errno));
81     return INVALID_FD;
82   }
83 
84   timeval socket_timeout{
85       .tv_sec = 3,
86       .tv_usec = 0,
87   };
88   int ret = setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
89   if (ret == -1) {
90     LOG_ERROR("can't control socket fd: %s", strerror(errno));
91     return INVALID_FD;
92   }
93   return socket_fd;
94 }
95 }  // namespace
96 
97 namespace bluetooth {
98 namespace hal {
99 
100 class HciHalHost : public HciHal {
101  public:
registerIncomingPacketCallback(HciHalCallbacks * callback)102   void registerIncomingPacketCallback(HciHalCallbacks* callback) override {
103     std::lock_guard<std::mutex> lock(api_mutex_);
104     LOG_INFO("%s before", __func__);
105     {
106       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
107       ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr);
108       incoming_packet_callback_ = callback;
109     }
110     LOG_INFO("%s after", __func__);
111   }
112 
unregisterIncomingPacketCallback()113   void unregisterIncomingPacketCallback() override {
114     std::lock_guard<std::mutex> lock(api_mutex_);
115     LOG_INFO("%s before", __func__);
116     {
117       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
118       incoming_packet_callback_ = nullptr;
119     }
120     LOG_INFO("%s after", __func__);
121   }
122 
sendHciCommand(HciPacket command)123   void sendHciCommand(HciPacket command) override {
124     std::lock_guard<std::mutex> lock(api_mutex_);
125     ASSERT(sock_fd_ != INVALID_FD);
126     std::vector<uint8_t> packet = std::move(command);
127     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
128     packet.insert(packet.cbegin(), kH4Command);
129     write_to_fd(packet);
130   }
131 
sendAclData(HciPacket data)132   void sendAclData(HciPacket data) override {
133     std::lock_guard<std::mutex> lock(api_mutex_);
134     ASSERT(sock_fd_ != INVALID_FD);
135     std::vector<uint8_t> packet = std::move(data);
136     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
137     packet.insert(packet.cbegin(), kH4Acl);
138     write_to_fd(packet);
139   }
140 
sendScoData(HciPacket data)141   void sendScoData(HciPacket data) override {
142     std::lock_guard<std::mutex> lock(api_mutex_);
143     ASSERT(sock_fd_ != INVALID_FD);
144     std::vector<uint8_t> packet = std::move(data);
145     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::SCO);
146     packet.insert(packet.cbegin(), kH4Sco);
147     write_to_fd(packet);
148   }
149 
sendIsoData(HciPacket data)150   void sendIsoData(HciPacket data) override {
151     std::lock_guard<std::mutex> lock(api_mutex_);
152     ASSERT(sock_fd_ != INVALID_FD);
153     std::vector<uint8_t> packet = std::move(data);
154     btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ISO);
155     packet.insert(packet.cbegin(), kH4Iso);
156     write_to_fd(packet);
157   }
158 
159  protected:
ListDependencies(ModuleList * list) const160   void ListDependencies(ModuleList* list) const {
161     list->add<metrics::CounterMetrics>();
162     list->add<SnoopLogger>();
163   }
164 
Start()165   void Start() override {
166     std::lock_guard<std::mutex> lock(api_mutex_);
167     ASSERT(sock_fd_ == INVALID_FD);
168     sock_fd_ = ConnectToSocket();
169     ASSERT(sock_fd_ != INVALID_FD);
170     reactable_ = hci_incoming_thread_.GetReactor()->Register(
171         sock_fd_,
172         common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)),
173         common::Bind(&HciHalHost::send_packet_ready, common::Unretained(this)));
174     hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, os::Reactor::REACT_ON_READ_ONLY);
175     btsnoop_logger_ = GetDependency<SnoopLogger>();
176     LOG_INFO("HAL opened successfully");
177   }
178 
Stop()179   void Stop() override {
180     std::lock_guard<std::mutex> lock(api_mutex_);
181     LOG_INFO("HAL is closing");
182     if (reactable_ != nullptr) {
183       hci_incoming_thread_.GetReactor()->Unregister(reactable_);
184       LOG_INFO("HAL is stopping, start waiting for last callback");
185       // Wait up to 1 second for the last incoming packet callback to finish
186       hci_incoming_thread_.GetReactor()->WaitForUnregisteredReactable(std::chrono::milliseconds(1000));
187       LOG_INFO("HAL is stopping, finished waiting for last callback");
188       ASSERT(sock_fd_ != INVALID_FD);
189     }
190     reactable_ = nullptr;
191     {
192       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
193       incoming_packet_callback_ = nullptr;
194     }
195     ::close(sock_fd_);
196     sock_fd_ = INVALID_FD;
197     LOG_INFO("HAL is closed");
198   }
199 
ToString() const200   std::string ToString() const override {
201     return std::string("HciHalHost");
202   }
203 
204  private:
205   // Held when APIs are called, NOT to be held during callbacks
206   std::mutex api_mutex_;
207   HciHalCallbacks* incoming_packet_callback_ = nullptr;
208   std::mutex incoming_packet_callback_mutex_;
209   int sock_fd_ = INVALID_FD;
210   bluetooth::os::Thread hci_incoming_thread_ =
211       bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL);
212   bluetooth::os::Reactor::Reactable* reactable_ = nullptr;
213   std::queue<std::vector<uint8_t>> hci_outgoing_queue_;
214   SnoopLogger* btsnoop_logger_ = nullptr;
215 
write_to_fd(HciPacket packet)216   void write_to_fd(HciPacket packet) {
217     // TODO: replace this with new queue when it's ready
218     hci_outgoing_queue_.emplace(packet);
219     if (hci_outgoing_queue_.size() == 1) {
220       hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, os::Reactor::REACT_ON_READ_WRITE);
221     }
222   }
223 
send_packet_ready()224   void send_packet_ready() {
225     std::lock_guard<std::mutex> lock(api_mutex_);
226     if (hci_outgoing_queue_.empty()) return;
227     auto packet_to_send = hci_outgoing_queue_.front();
228     auto bytes_written = write(sock_fd_, (void*)packet_to_send.data(), packet_to_send.size());
229     hci_outgoing_queue_.pop();
230     if (bytes_written == -1) {
231       abort();
232     }
233     if (hci_outgoing_queue_.empty()) {
234       hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, os::Reactor::REACT_ON_READ_ONLY);
235     }
236   }
237 
socketRecvAll(void * buffer,int bufferLen)238   bool socketRecvAll(void* buffer, int bufferLen) {
239     auto buf = static_cast<char*>(buffer);
240     while (bufferLen > 0) {
241       ssize_t ret;
242       RUN_NO_INTR(ret = recv(sock_fd_, buf, bufferLen, 0));
243       if (ret <= 0) {
244         return false;
245       }
246       buf += ret;
247       bufferLen -= ret;
248     }
249     return true;
250   }
251 
incoming_packet_received()252   void incoming_packet_received() {
253     {
254       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
255       if (incoming_packet_callback_ == nullptr) {
256         LOG_INFO("Dropping a packet");
257         return;
258       }
259     }
260     uint8_t buf[kBufSize] = {};
261 
262     ssize_t received_size;
263     RUN_NO_INTR(received_size = recv(sock_fd_, buf, kH4HeaderSize, 0));
264     ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
265     if (received_size == 0) {
266       LOG_WARN("Can't read H4 header. EOF received");
267       raise(SIGINT);
268       return;
269     }
270 
271     if (buf[0] == kH4Event) {
272       ASSERT_LOG(
273           socketRecvAll(buf + kH4HeaderSize, kHciEvtHeaderSize), "Can't receive from socket: %s", strerror(errno));
274 
275       uint8_t hci_evt_parameter_total_length = buf[2];
276       ASSERT_LOG(
277           socketRecvAll(buf + kH4HeaderSize + kHciEvtHeaderSize, hci_evt_parameter_total_length),
278           "Can't receive from socket: %s",
279           strerror(errno));
280 
281       HciPacket receivedHciPacket;
282       receivedHciPacket.assign(
283           buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + hci_evt_parameter_total_length);
284       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
285       {
286         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
287         if (incoming_packet_callback_ == nullptr) {
288           LOG_INFO("Dropping an event after processing");
289           return;
290         }
291         incoming_packet_callback_->hciEventReceived(receivedHciPacket);
292       }
293     }
294 
295     if (buf[0] == kH4Acl) {
296       ASSERT_LOG(
297           socketRecvAll(buf + kH4HeaderSize, kHciAclHeaderSize), "Can't receive from socket: %s", strerror(errno));
298 
299       uint16_t hci_acl_data_total_length = (buf[4] << 8) + buf[3];
300       ASSERT_LOG(
301           socketRecvAll(buf + kH4HeaderSize + kHciAclHeaderSize, hci_acl_data_total_length),
302           "Can't receive from socket: %s",
303           strerror(errno));
304 
305       HciPacket receivedHciPacket;
306       receivedHciPacket.assign(
307           buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + hci_acl_data_total_length);
308       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
309       {
310         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
311         if (incoming_packet_callback_ == nullptr) {
312           LOG_INFO("Dropping an ACL packet after processing");
313           return;
314         }
315         incoming_packet_callback_->aclDataReceived(receivedHciPacket);
316       }
317     }
318 
319     if (buf[0] == kH4Sco) {
320       ASSERT_LOG(
321           socketRecvAll(buf + kH4HeaderSize, kHciScoHeaderSize), "Can't receive from socket: %s", strerror(errno));
322 
323       uint8_t hci_sco_data_total_length = buf[3];
324       ASSERT_LOG(
325           socketRecvAll(buf + kH4HeaderSize + kHciScoHeaderSize, hci_sco_data_total_length),
326           "Can't receive from socket: %s",
327           strerror(errno));
328 
329       HciPacket receivedHciPacket;
330       receivedHciPacket.assign(
331           buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + hci_sco_data_total_length);
332       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::SCO);
333       {
334         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
335         if (incoming_packet_callback_ == nullptr) {
336           LOG_INFO("Dropping a SCO packet after processing");
337           return;
338         }
339         incoming_packet_callback_->scoDataReceived(receivedHciPacket);
340       }
341     }
342 
343     if (buf[0] == kH4Iso) {
344       ASSERT_LOG(
345           socketRecvAll(buf + kH4HeaderSize, kHciIsoHeaderSize), "Can't receive from socket: %s", strerror(errno));
346 
347       uint16_t hci_iso_data_total_length = ((buf[4] & 0x3f) << 8) + buf[3];
348       ASSERT_LOG(
349           socketRecvAll(buf + kH4HeaderSize + kHciIsoHeaderSize, hci_iso_data_total_length),
350           "Can't receive from socket: %s",
351           strerror(errno));
352 
353       HciPacket receivedHciPacket;
354       receivedHciPacket.assign(
355           buf + kH4HeaderSize, buf + kH4HeaderSize + kHciIsoHeaderSize + hci_iso_data_total_length);
356       btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ISO);
357       {
358         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
359         if (incoming_packet_callback_ == nullptr) {
360           LOG_INFO("Dropping a ISO packet after processing");
361           return;
362         }
363         incoming_packet_callback_->isoDataReceived(receivedHciPacket);
364       }
365     }
366     memset(buf, 0, kBufSize);
367   }
368 };
369 
__anon34660c4c0202() 370 const ModuleFactory HciHal::Factory = ModuleFactory([]() { return new HciHalHost(); });
371 
372 }  // namespace hal
373 }  // namespace bluetooth
374