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 <sys/uio.h>
19 #include <termios.h>
20 #include <unistd.h>
21 #include <iomanip>
22 #include <ios>
23 #include <optional>
24
25 #include <gflags/gflags.h>
26
27 #include "android-base/logging.h"
28
29 #include "hci/h4_packetizer.h"
30
31 // Copied from net/bluetooth/hci.h
32 #define HCI_ACLDATA_PKT 0x02
33 #define HCI_SCODATA_PKT 0x03
34 #define HCI_EVENT_PKT 0x04
35 #define HCI_ISODATA_PKT 0x05
36 #define HCI_VENDOR_PKT 0xff
37 #define HCI_MAX_ACL_SIZE 1024
38 #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
39
40 // Include H4 header byte, and reserve more buffer size in the case of excess
41 // packet.
42 constexpr const size_t kBufferSize = (HCI_MAX_FRAME_SIZE + 1) * 2;
43
44 constexpr const char* kVhciDev = "/dev/vhci";
45 DEFINE_string(virtio_console_dev, "", "virtio-console device path");
46
send(int fd_,uint8_t type,const uint8_t * data,size_t length)47 ssize_t send(int fd_, uint8_t type, const uint8_t* data, size_t length) {
48 struct iovec iov[] = {{&type, sizeof(type)},
49 {const_cast<uint8_t*>(data), length}};
50 ssize_t ret = 0;
51 do {
52 ret = TEMP_FAILURE_RETRY(writev(fd_, iov, sizeof(iov) / sizeof(iov[0])));
53 } while (-1 == ret && EAGAIN == errno);
54 if (ret == -1) {
55 PLOG(ERROR) << "virtio-console to vhci failed";
56 }
57 return ret;
58 }
59
forward(int from_fd,int to_fd,unsigned char * buf)60 ssize_t forward(int from_fd, int to_fd, unsigned char* buf) {
61 ssize_t count = TEMP_FAILURE_RETRY(read(from_fd, buf, kBufferSize));
62 if (count < 0) {
63 PLOG(ERROR) << "read failed";
64 return count;
65 }
66 if (count == 0) {
67 return count;
68 }
69 // TODO(b/182245475) Ignore HCI_VENDOR_PKT
70 // because root-canal cannot handle it.
71 if (buf[0] == HCI_VENDOR_PKT) {
72 LOG(INFO) << "Ignoring VENDOR packet";
73 return 0;
74 }
75 count = TEMP_FAILURE_RETRY(write(to_fd, buf, count));
76 if (count < 0) {
77 PLOG(ERROR) << "write failed, type: 0x" << std::hex << std::setw(2)
78 << std::setfill('0') << (unsigned)buf[0];
79 }
80 return count;
81 }
82
setTerminalRaw(int fd_)83 int setTerminalRaw(int fd_) {
84 termios terminal_settings;
85 int rval = tcgetattr(fd_, &terminal_settings);
86 if (rval < 0) {
87 return rval;
88 }
89 cfmakeraw(&terminal_settings);
90 rval = tcsetattr(fd_, TCSANOW, &terminal_settings);
91 return rval;
92 }
93
main(int argc,char ** argv)94 int main(int argc, char** argv) {
95 gflags::ParseCommandLineFlags(&argc, &argv, true);
96
97 int vhci_fd = open(kVhciDev, O_RDWR);
98 if (vhci_fd < 0) {
99 PLOG(ERROR) << "Unable to open " << kVhciDev;
100 }
101 int virtio_fd = open(FLAGS_virtio_console_dev.c_str(), O_RDWR);
102 if (virtio_fd < 0) {
103 PLOG(ERROR) << "Unable to open " << FLAGS_virtio_console_dev;
104 }
105 int set_result = setTerminalRaw(virtio_fd);
106 if (set_result < 0) {
107 PLOG(ERROR) << "setTerminalRaw failed " << FLAGS_virtio_console_dev;
108 }
109
110 struct pollfd fds[2];
111
112 fds[0].fd = vhci_fd;
113 fds[0].events = POLLIN;
114 fds[1].fd = virtio_fd;
115 fds[1].events = POLLIN;
116 unsigned char buf[kBufferSize];
117
118 auto h4 = rootcanal::H4Packetizer(
119 virtio_fd,
120 [](const std::vector<uint8_t>& /* raw_command */) {
121 LOG(ERROR)
122 << "Unexpected command: command pkt shouldn't be sent as response.";
123 },
124 [vhci_fd](const std::vector<uint8_t>& raw_event) {
125 send(vhci_fd, HCI_EVENT_PKT, raw_event.data(), raw_event.size());
126 },
127 [vhci_fd](const std::vector<uint8_t>& raw_acl) {
128 send(vhci_fd, HCI_ACLDATA_PKT, raw_acl.data(), raw_acl.size());
129 },
130 [vhci_fd](const std::vector<uint8_t>& raw_sco) {
131 send(vhci_fd, HCI_SCODATA_PKT, raw_sco.data(), raw_sco.size());
132 },
133 [vhci_fd](const std::vector<uint8_t>& raw_iso) {
134 send(vhci_fd, HCI_ISODATA_PKT, raw_iso.data(), raw_iso.size());
135 },
136 []() { LOG(INFO) << "HCI socket device disconnected"; });
137
138 // Flag to drop any data left in the virtio-console buffer
139 // before any command is received from vhci: corrupted data
140 // could be left there from android restarting.
141 bool before_first_command = true;
142
143 while (true) {
144 int ret = TEMP_FAILURE_RETRY(poll(fds, 2, -1));
145 if (ret < 0) {
146 PLOG(ERROR) << "poll failed";
147 continue;
148 }
149 if (fds[1].revents & POLLHUP) {
150 LOG(ERROR) << "PollHUP";
151 usleep(50 * 1000);
152 continue;
153 }
154 if (fds[1].revents & (POLLIN | POLLERR)) {
155 if (before_first_command) {
156 // Drop any data left in the virtio-console from a previous reset.
157 ssize_t bytes = TEMP_FAILURE_RETRY(read(virtio_fd, buf, kBufferSize));
158 if (bytes < 0) {
159 LOG(ERROR) << "virtio_fd ready, but read failed " << strerror(errno);
160 continue;
161 }
162 if (bytes == 1) {
163 LOG(INFO) << "Discarding 1 byte from virtio_fd: "
164 << "0x" << std::hex << (unsigned)buf[0];
165 } else {
166 LOG(INFO) << "Discarding " << bytes << " bytes from virtio_fd: "
167 << "0x" << std::hex << (unsigned)buf[0] << " .. 0x"
168 << std::hex << (unsigned)buf[bytes - 1];
169 }
170 continue;
171 }
172 // 'virtio-console to vhci' depends on H4Packetizer because vhci expects
173 // full packet, but the data from virtio-console could be partial.
174 h4.OnDataReady(virtio_fd);
175 }
176 if (fds[0].revents & (POLLIN | POLLERR)) {
177 ssize_t transferred = forward(vhci_fd, virtio_fd, buf);
178 if (transferred > 0 && before_first_command) {
179 LOG(INFO) << "Received first command from VHCI device; enabling reads "
180 "from virtio";
181 before_first_command = false;
182 }
183 }
184 }
185 }
186