xref: /aosp_15_r20/tools/netsim/src/hci/hci_packet_transport.cc (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
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 #include "hci/hci_packet_transport.h"
16 
17 #include <limits>
18 #include <memory>
19 #include <optional>
20 
21 #include "model/hci/hci_transport.h"
22 #include "netsim-daemon/src/ffi.rs.h"
23 #include "netsim/hci_packet.pb.h"
24 #include "netsim/stats.pb.h"
25 #include "rust/cxx.h"
26 #include "util/log.h"
27 
28 using netsim::packet::HCIPacket;
29 
30 namespace netsim {
31 namespace hci {
32 
33 std::unordered_map<uint32_t, std::shared_ptr<HciPacketTransport>>
34     rootcanal_id_to_transport_;
35 
36 /**
37  * @class HciPacketTransport
38  *
39  * Connects hci packets between packet_hub and rootcanal.
40  *
41  */
HciPacketTransport(uint32_t chip_id,std::shared_ptr<rootcanal::AsyncManager> async_manager)42 HciPacketTransport::HciPacketTransport(
43     uint32_t chip_id, std::shared_ptr<rootcanal::AsyncManager> async_manager)
44     : rootcanalId(std::nullopt),
45       netsimChipId(chip_id),
46       mAsyncManager(std::move(async_manager)) {}
47 
48 /**
49  * @brief Connect the phy device to the transport
50  *
51  * @param - rootcanal_id identifier of the owning device
52  *
53  * @param - chip_id identifier generated from netsimd
54  */
Connect(rootcanal::PhyDevice::Identifier rootcanal_id)55 void HciPacketTransport::Connect(
56     rootcanal::PhyDevice::Identifier rootcanal_id) {
57   assert(!rootcanalId.has_value());
58   rootcanalId.emplace(rootcanal_id);
59 }
60 
61 // Called by HCITransport (rootcanal)
Send(rootcanal::PacketType packet_type,const std::vector<uint8_t> & data)62 void HciPacketTransport::Send(rootcanal::PacketType packet_type,
63                               const std::vector<uint8_t> &data) {
64   // The packet types have standard values, converting from
65   // rootcanal::PacketType to HCIPacket_PacketType is safe.
66   packet::HCIPacket_PacketType hci_packet_type =
67       static_cast<packet::HCIPacket_PacketType>(packet_type);
68   if (!rootcanalId.has_value()) {
69     BtsLogWarn("hci_packet_transport: response with no device.");
70     return;
71   }
72   // Send response to transport dispatcher.
73   netsim::wireless::HandleResponse(netsimChipId, data, hci_packet_type);
74 }
75 
76 // Called by HCITransport (rootcanal)
RegisterCallbacks(rootcanal::PacketCallback packetCallback,rootcanal::CloseCallback closeCallback)77 void HciPacketTransport::RegisterCallbacks(
78     rootcanal::PacketCallback packetCallback,
79     rootcanal::CloseCallback closeCallback) {
80   BtsLogInfo("hci_packet_transport: registered");
81   mPacketCallback = packetCallback;
82   mCloseCallback = closeCallback;
83 }
84 
85 // Called by HCITransport (rootcanal)
Tick()86 void HciPacketTransport::Tick() {}
87 
Request(packet::HCIPacket_PacketType packet_type,const std::shared_ptr<std::vector<uint8_t>> & packet)88 void HciPacketTransport::Request(
89     packet::HCIPacket_PacketType packet_type,
90     const std::shared_ptr<std::vector<uint8_t>> &packet) {
91   assert(mPacketCallback);
92   // The packet types have standard values, converting from
93   // HCIPacket_PacketType to rootcanal::PacketType is safe.
94   rootcanal::PacketType rootcanal_packet_type =
95       static_cast<rootcanal::PacketType>(packet_type);
96   auto beforeScheduleTime = std::chrono::steady_clock::now();
97   mAsyncManager->Synchronize(
98       [this, rootcanal_packet_type, packet, beforeScheduleTime]() {
99         auto elapsedTime =
100             std::chrono::duration_cast<std::chrono::milliseconds>(
101                 std::chrono::steady_clock::now() - beforeScheduleTime)
102                 .count();
103         // If the elapsed time of the packet delivery is greater than 100ms,
104         // report invalid packet with DELAYED reasoning.
105         if (elapsedTime > 100) {
106           // Create a new vector to hold the combined data
107           std::vector<uint8_t> combinedPacket;
108 
109           // Prepend rootcanal_packet_type
110           combinedPacket.push_back(static_cast<uint8_t>(rootcanal_packet_type));
111 
112           // Append the original packet data
113           combinedPacket.insert(combinedPacket.end(), packet->begin(),
114                                 packet->end());
115 
116           // Report Invalid Packet
117           netsim::hci::facade::ReportInvalidPacket(
118               this->rootcanalId.value(),
119               stats::InvalidPacket_Reason::InvalidPacket_Reason_DELAYED,
120               "Delayed packet with " + std::to_string(elapsedTime) +
121                   " milliseconds",
122               combinedPacket);
123         }
124         mPacketCallback(rootcanal_packet_type, packet);
125       });
126 }
127 
Add(rootcanal::PhyDevice::Identifier rootcanal_id,const std::shared_ptr<HciPacketTransport> & transport)128 void HciPacketTransport::Add(
129     rootcanal::PhyDevice::Identifier rootcanal_id,
130     const std::shared_ptr<HciPacketTransport> &transport) {
131   transport->Connect(rootcanal_id);
132   rootcanal_id_to_transport_[rootcanal_id] = transport;
133 }
134 
Remove(rootcanal::PhyDevice::Identifier rootcanal_id)135 void HciPacketTransport::Remove(rootcanal::PhyDevice::Identifier rootcanal_id) {
136   BtsLogInfo("hci_packet_transport remove from netsim");
137   if (rootcanal_id_to_transport_.find(rootcanal_id) !=
138           rootcanal_id_to_transport_.end() &&
139       rootcanal_id_to_transport_[rootcanal_id]) {
140     // Calls HciDevice::Close, will disconnect AclHandles with
141     // CONNECTION_TIMEOUT, and call TestModel::CloseCallback.
142     rootcanal_id_to_transport_[rootcanal_id]->mCloseCallback();
143   }
144 }
145 
146 // Called by HciDevice::Close
Close()147 void HciPacketTransport::Close() {
148   if (rootcanalId.has_value()) {
149     rootcanal_id_to_transport_.erase(rootcanalId.value());
150   }
151   BtsLogInfo("hci_packet_transport close from rootcanal");
152   rootcanalId = std::nullopt;
153 }
154 
155 // handle_request is the main entry for incoming packets called by
156 // netsim::packet_hub
157 //
158 // Transfer the request to the HciTransport to deliver to Rootcanal via the
159 // acl/sco/iso/command callback methods under synchronization.
handle_bt_request(uint32_t rootcanal_id,packet::HCIPacket_PacketType packet_type,const std::shared_ptr<std::vector<uint8_t>> & packet)160 void handle_bt_request(uint32_t rootcanal_id,
161                        packet::HCIPacket_PacketType packet_type,
162                        const std::shared_ptr<std::vector<uint8_t>> &packet) {
163   if (rootcanal_id_to_transport_.find(rootcanal_id) !=
164           rootcanal_id_to_transport_.end() &&
165       rootcanal_id_to_transport_[rootcanal_id]) {
166     auto transport = rootcanal_id_to_transport_[rootcanal_id];
167     transport->Request(packet_type, packet);
168   } else {
169     std::cout << "rootcanal_id_to_transport_ ids ";
170     for (auto [k, _] : rootcanal_id_to_transport_) std::cout << k << " ";
171     std::cout << std::endl;
172     BtsLogWarn(
173         "hci_packet_transport: handle_request with no transport for device "
174         "with rootcanal_id: %d",
175         rootcanal_id);
176   }
177 }
178 
HandleBtRequestCxx(uint32_t rootcanal_id,uint8_t packet_type,const rust::Vec<uint8_t> & packet)179 void HandleBtRequestCxx(uint32_t rootcanal_id, uint8_t packet_type,
180                         const rust::Vec<uint8_t> &packet) {
181   std::vector<uint8_t> buffer(packet.begin(), packet.end());
182   auto packet_ptr = std::make_shared<std::vector<uint8_t>>(buffer);
183   handle_bt_request(rootcanal_id,
184                     static_cast<packet::HCIPacket_PacketType>(packet_type),
185                     packet_ptr);
186 }
187 
188 }  // namespace hci
189 }  // namespace netsim
190