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