1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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 /// Connect HCI file descriptors to root canal.
16
17 #include "fd_startup.h"
18
19 #include <google/protobuf/util/json_util.h>
20 #include <sys/uio.h>
21 #include <unistd.h>
22
23 #include <memory>
24 #include <thread>
25
26 #include "common.pb.h"
27 #include "controller/scene_controller.h"
28 #include "hci/bluetooth_facade.h"
29 #include "model/hci/h4_parser.h"
30 #include "model/hci/hci_transport.h"
31 #include "startup.pb.h"
32 #include "util/log.h"
33
34 namespace netsim {
35 namespace hci {
36 namespace {
37
38 enum HCIPacket : int {
39 PACKET_TYPE_UNSPECIFIED = 0,
40 PACKET_TYPE_HCI_COMMAND = 1,
41 PACKET_TYPE_ACL = 2,
42 PACKET_TYPE_SCO = 3,
43 PACKET_TYPE_EVENT = 4,
44 PACKET_TYPE_ISO = 5
45 };
46
47 // Class to move packets between root canal and file descriptor.
48
49 class FdHciForwarder : public rootcanal::HciTransport {
50 public:
~FdHciForwarder()51 ~FdHciForwarder() {}
52
FdHciForwarder(std::string name,int fd_in,int fd_out)53 FdHciForwarder(std::string name, int fd_in, int fd_out)
54 : fd_in_(fd_in), fd_out_(fd_out), name_(std::move(name)) {}
55
56 // Called by HCITransport (rootcanal)
SendEvent(const std::vector<uint8_t> & data)57 void SendEvent(const std::vector<uint8_t> &data) override {
58 this->Write(HCIPacket::PACKET_TYPE_EVENT, data.data(), data.size());
59 }
60
61 // Called by HCITransport (rootcanal)
SendAcl(const std::vector<uint8_t> & data)62 void SendAcl(const std::vector<uint8_t> &data) override {
63 this->Write(HCIPacket::PACKET_TYPE_ACL, data.data(), data.size());
64 }
65
66 // Called by HCITransport (rootcanal)
SendSco(const std::vector<uint8_t> & data)67 void SendSco(const std::vector<uint8_t> &data) override {
68 this->Write(HCIPacket::PACKET_TYPE_SCO, data.data(), data.size());
69 }
70
71 // Called by HCITransport (rootcanal)
SendIso(const std::vector<uint8_t> & data)72 void SendIso(const std::vector<uint8_t> &data) override {
73 this->Write(HCIPacket::PACKET_TYPE_ISO, data.data(), data.size());
74 }
75
76 // A wrapper for the HCITransport that uses shared ptrs.
77
SharedPacketCallback(const rootcanal::PacketCallback & cb,const std::vector<uint8_t> & raw_packet)78 static void SharedPacketCallback(const rootcanal::PacketCallback &cb,
79 const std::vector<uint8_t> &raw_packet) {
80 std::shared_ptr<std::vector<uint8_t>> packet_copy =
81 std::make_shared<std::vector<uint8_t>>(raw_packet);
82 cb(packet_copy);
83 }
84 // Called by HCITransport (rootcanal)
85 // This case is simular to hci_socket_transport.cc
RegisterCallbacks(rootcanal::PacketCallback command_cb,rootcanal::PacketCallback acl_cb,rootcanal::PacketCallback sco_cb,rootcanal::PacketCallback iso_cb,rootcanal::CloseCallback close_cb)86 void RegisterCallbacks(rootcanal::PacketCallback command_cb,
87 rootcanal::PacketCallback acl_cb,
88 rootcanal::PacketCallback sco_cb,
89 rootcanal::PacketCallback iso_cb,
90 rootcanal::CloseCallback close_cb) override {
91 h4_parser_ = std::make_unique<rootcanal::H4Parser>(
92 [command_cb](const std::vector<uint8_t> &raw_command) {
93 SharedPacketCallback(command_cb, raw_command);
94 },
95 [](const std::vector<uint8_t> &) {
96 BtsLog("Unexpected Event in FdTransport!");
97 },
98 [acl_cb](const std::vector<uint8_t> &raw_acl) {
99 SharedPacketCallback(acl_cb, raw_acl);
100 },
101 [sco_cb](const std::vector<uint8_t> &raw_sco) {
102 SharedPacketCallback(sco_cb, raw_sco);
103 },
104 [iso_cb](const std::vector<uint8_t> &raw_iso) {
105 SharedPacketCallback(iso_cb, raw_iso);
106 });
107 this->close_cb_ = close_cb;
108 // start the reader thread
109 this->reader_ = std::move(std::thread([&] { StartReader(); }));
110 }
111
112 // Called by HCITransport (rootcanal)
Close()113 void Close() override {
114 BtsLog("netsim - Close called for %s", name_.c_str());
115 close(fd_in_);
116 close(fd_out_);
117 }
118
119 // Called by HCITransport (rootcanal)
Tick()120 void Tick() override {}
121
122 private:
123 const int fd_in_, fd_out_;
124 std::thread reader_;
125 bool disconnected_ = false;
126 rootcanal::CloseCallback close_cb_;
127 std::unique_ptr<rootcanal::H4Parser> h4_parser_;
128 const std::string name_;
129
130 // Write packets from rootcanal back to guest os
Write(uint8_t type,const uint8_t * data,size_t length)131 int Write(uint8_t type, const uint8_t *data, size_t length) {
132 struct iovec iov[] = {{&type, sizeof(type)},
133 {const_cast<uint8_t *>(data), length}};
134 ssize_t ret = 0;
135 do {
136 ret = writev(fd_in_, iov, sizeof(iov) / sizeof(iov[0]));
137 } while (-1 == ret && EAGAIN == errno);
138 if (ret == -1) {
139 BtsLog("Netsim: Error writing (%s)", strerror(errno));
140 } else if (ret < static_cast<ssize_t>(length + 1)) {
141 BtsLog("Netsim: %d / %d bytes written - something went wrong...",
142 static_cast<int>(ret), static_cast<int>(length + 1));
143 }
144 return ret;
145 }
146
147 // Start reading packets from guest os fd and sending to root canal.
StartReader()148 void StartReader() {
149 while (!disconnected_) {
150 ssize_t bytes_to_read = h4_parser_->BytesRequested();
151 std::vector<uint8_t> buffer(bytes_to_read);
152 ssize_t bytes_read;
153 bytes_read = read(fd_out_, buffer.data(), bytes_to_read);
154 if (bytes_read == 0) {
155 BtsLog("remote disconnected -- %s", name_.c_str());
156 disconnected_ = true;
157 close_cb_();
158 break;
159 } else if (bytes_read < 0) {
160 if (errno == EAGAIN) {
161 // No data, try again later.
162 continue;
163 } else if (errno == ECONNRESET) {
164 // They probably rejected our packet
165 disconnected_ = true;
166 close_cb_();
167 break;
168 } else {
169 BtsLog("Read error in %d %s", h4_parser_->CurrentState(),
170 strerror(errno));
171 }
172 } else {
173 h4_parser_->Consume(buffer.data(), bytes_read);
174 }
175 }
176 }
177 };
178
179 // Private implementation
180
181 class FdStartupImpl : public FdStartup {
182 public:
183 // Disallow copy and assign
184 FdStartupImpl(const FdStartupImpl &) = delete;
185 FdStartupImpl &operator=(const FdStartupImpl &) = delete;
186
FdStartupImpl()187 FdStartupImpl() {}
188
189 // Connect multiple fd endpoints
190
Connect(const std::string & startup_str)191 bool Connect(const std::string &startup_str) override {
192 netsim::startup::StartupInfo info;
193 google::protobuf::util::JsonParseOptions options;
194 auto status = JsonStringToMessage(startup_str, &info, options);
195
196 if (!status.ok()) {
197 BtsLog("FdStartup failed to parse json '%s' - %s", startup_str.c_str(),
198 status.ToString().c_str());
199 return false;
200 }
201
202 for (const auto &device : info.devices()) {
203 auto name = device.name();
204 for (const auto &chip : device.chips()) {
205 if (chip.kind() == common::ChipKind::BLUETOOTH) {
206 auto fd_in = chip.fd_in();
207 auto fd_out = chip.fd_out();
208
209 BtsLog("Connecting %s on fd_in:%d, fd_out:%d", name.c_str(), fd_in,
210 fd_out);
211
212 std::shared_ptr<rootcanal::HciTransport> transport =
213 std::make_shared<FdHciForwarder>(name, fd_in, fd_out);
214 auto guid =
215 name + ":" + std::to_string(fd_in) + ":" + std::to_string(fd_out);
216 netsim::controller::SceneController::Singleton().AddChip(
217 guid, name, common::ChipKind::BLUETOOTH);
218
219 BtsLog("FdHciForwarder is not supported");
220 }
221 }
222 }
223 return true;
224 }
225 };
226
227 } // namespace
228
~FdStartup()229 FdStartup::~FdStartup(){};
230
231 // Public constructor for FdStartup that returns private implementation.
232
Create()233 std::unique_ptr<FdStartup> FdStartup::Create() {
234 std::cerr << "Creating FdStartup\n";
235 return std::make_unique<FdStartupImpl>();
236 }
237
238 } // namespace hci
239 } // namespace netsim
240