• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fcntl.h>
17 #include <sys/poll.h>
18 #include <unistd.h>
19 #include <ios>
20 #include <mutex>
21 
22 #include <android-base/logging.h>
23 #include <gflags/gflags.h>
24 #include <thread>
25 
26 #include "common/libs/fs/shared_buf.h"
27 #include "common/libs/fs/shared_fd.h"
28 #include "host/libs/config/cuttlefish_config.h"
29 #include "host/libs/config/logging.h"
30 
31 // Copied from net/bluetooth/hci.h
32 #define HCI_MAX_ACL_SIZE 1024
33 #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
34 
35 // Include H4 header byte, and reserve more buffer size in the case of excess
36 // packet.
37 constexpr const size_t kBufferSize = (HCI_MAX_FRAME_SIZE + 1) * 2;
38 
39 DEFINE_int32(bt_in, -1, "A pipe for bt communication");
40 DEFINE_int32(bt_out, -1, "A pipe for bt communication");
41 DEFINE_int32(hci_port, -1, "A port for bt hci command");
42 DEFINE_int32(link_port, -1, "A pipe for bt link layer command");
43 DEFINE_int32(test_port, -1, "A pipe for rootcanal test channel");
44 
openSocket(cuttlefish::SharedFD * fd,int port)45 void openSocket(cuttlefish::SharedFD* fd, int port) {
46   static std::mutex mutex;
47   std::unique_lock<std::mutex> lock(mutex);
48   *fd = cuttlefish::SharedFD::SocketLocalClient(port, SOCK_STREAM);
49 }
50 
main(int argc,char ** argv)51 int main(int argc, char** argv) {
52   cuttlefish::DefaultSubprocessLogging(argv);
53   gflags::ParseCommandLineFlags(&argc, &argv, true);
54   auto bt_in = cuttlefish::SharedFD::Dup(FLAGS_bt_in);
55   if (!bt_in->IsOpen()) {
56     LOG(ERROR) << "Error dupping fd " << FLAGS_bt_in << ": "
57                << bt_in->StrError();
58     return 1;
59   }
60   close(FLAGS_bt_in);
61 
62   auto bt_out = cuttlefish::SharedFD::Dup(FLAGS_bt_out);
63   if (!bt_out->IsOpen()) {
64     LOG(ERROR) << "Error dupping fd " << FLAGS_bt_out << ": "
65                << bt_out->StrError();
66     return 1;
67   }
68   close(FLAGS_bt_out);
69   cuttlefish::SharedFD sock;
70   openSocket(&sock, FLAGS_hci_port);
71 
72   auto guest_to_host = std::thread([&]() {
73     while (true) {
74       char buf[kBufferSize];
75       auto read = bt_in->Read(buf, sizeof(buf));
76       while (cuttlefish::WriteAll(sock, buf, read) == -1) {
77         LOG(ERROR) << "failed to write to socket, retry.";
78         // Wait for the host process to be ready
79         sleep(1);
80         openSocket(&sock, FLAGS_hci_port);
81       }
82     }
83   });
84 
85   auto host_to_guest = std::thread([&]() {
86     while (true) {
87       char buf[kBufferSize];
88       auto read = sock->Read(buf, sizeof(buf));
89       if (read == -1) {
90         LOG(ERROR) << "failed to read from socket, retry.";
91         // Wait for the host process to be ready
92         sleep(1);
93         openSocket(&sock, FLAGS_hci_port);
94         continue;
95       }
96       cuttlefish::WriteAll(bt_out, buf, read);
97     }
98   });
99   guest_to_host.join();
100   host_to_guest.join();
101 }
102