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 "hci/hci_debug.h"
22 #include "hci_packet.pb.h"
23 #include "model/hci/hci_transport.h"
24 #include "packet_hub/packet_hub.h"
25 #include "util/log.h"
26
27 using netsim::packet::HCIPacket;
28
29 namespace netsim {
30 namespace hci {
31
32 std::unordered_map<uint32_t, std::shared_ptr<HciPacketTransport>>
33 device_to_transport_;
34
35 /**
36 * @class HciPacketTransport
37 *
38 * Connects hci packets between packet_hub and rootcanal.
39 *
40 */
HciPacketTransport(std::shared_ptr<rootcanal::AsyncManager> async_manager)41 HciPacketTransport::HciPacketTransport(
42 std::shared_ptr<rootcanal::AsyncManager> async_manager)
43 : mDeviceId(std::nullopt), mAsyncManager(std::move(async_manager)) {}
44
45 /**
46 * @brief Connect the phy device to the transport
47 *
48 * @param - device_id identifier of the owning device
49 */
Connect(rootcanal::PhyDevice::Identifier device_id)50 void HciPacketTransport::Connect(rootcanal::PhyDevice::Identifier device_id) {
51 assert(!mDeviceId.has_value());
52 mDeviceId.emplace(device_id);
53 }
54
55 // Called by HCITransport (rootcanal)
SendEvent(const std::vector<uint8_t> & data)56 void HciPacketTransport::SendEvent(const std::vector<uint8_t> &data) {
57 this->Response(HCIPacket::EVENT, data);
58 }
59
60 // Called by HCITransport (rootcanal)
SendAcl(const std::vector<uint8_t> & data)61 void HciPacketTransport::SendAcl(const std::vector<uint8_t> &data) {
62 this->Response(HCIPacket::ACL, data);
63 }
64
65 // Called by HCITransport (rootcanal)
SendSco(const std::vector<uint8_t> & data)66 void HciPacketTransport::SendSco(const std::vector<uint8_t> &data) {
67 this->Response(HCIPacket::SCO, data);
68 }
69
70 // Called by HCITransport (rootcanal)
SendIso(const std::vector<uint8_t> & data)71 void HciPacketTransport::SendIso(const std::vector<uint8_t> &data) {
72 this->Response(HCIPacket::ISO, data);
73 }
74
75 // Called by HCITransport (rootcanal)
RegisterCallbacks(rootcanal::PacketCallback commandCallback,rootcanal::PacketCallback aclCallback,rootcanal::PacketCallback scoCallback,rootcanal::PacketCallback isoCallback,rootcanal::CloseCallback closeCallback)76 void HciPacketTransport::RegisterCallbacks(
77 rootcanal::PacketCallback commandCallback,
78 rootcanal::PacketCallback aclCallback,
79 rootcanal::PacketCallback scoCallback,
80 rootcanal::PacketCallback isoCallback,
81 rootcanal::CloseCallback closeCallback) {
82 BtsLog("hci_packet_transport: registered");
83 mCommandCallback = commandCallback;
84 mAclCallback = aclCallback;
85 mScoCallback = scoCallback;
86 mIsoCallback = isoCallback;
87 mCloseCallback = closeCallback;
88 }
89
90 // Called by HCITransport (rootcanal)
Tick()91 void HciPacketTransport::Tick() {}
92
Request(packet::HCIPacket_PacketType packet_type,const std::shared_ptr<std::vector<uint8_t>> & packet)93 void HciPacketTransport::Request(
94 packet::HCIPacket_PacketType packet_type,
95 const std::shared_ptr<std::vector<uint8_t>> &packet) {
96 auto packet_callback = PacketTypeCallback(packet_type);
97 if (!packet_callback) {
98 BtsLog("hci_transport: unknown packet_callback");
99 return;
100 }
101 if (packet_type == HCIPacket::COMMAND) {
102 auto cmd = HciCommandToString(packet->at(0), packet->at(1));
103 }
104 // Copy the packet bytes for rootcanal.
105 mAsyncManager->Synchronize(
106 [packet_callback, packet]() { packet_callback(packet); });
107 }
108
Add(rootcanal::PhyDevice::Identifier device_id,const std::shared_ptr<HciPacketTransport> & transport)109 void HciPacketTransport::Add(
110 rootcanal::PhyDevice::Identifier device_id,
111 const std::shared_ptr<HciPacketTransport> &transport) {
112 transport->Connect(device_id);
113 device_to_transport_[device_id] = transport;
114 }
115
Close()116 void HciPacketTransport::Close() {
117 if (mDeviceId.has_value()) {
118 device_to_transport_.erase(mDeviceId.value());
119 }
120
121 BtsLog("hci_packet_transport close from rootcanal");
122 mDeviceId = std::nullopt;
123 }
124
125 // Send response to packet_hub.
126 // TODO: future optimization by having rootcanal send shared_ptr.
Response(packet::HCIPacket_PacketType packet_type,const std::vector<uint8_t> & packet)127 void HciPacketTransport::Response(packet::HCIPacket_PacketType packet_type,
128 const std::vector<uint8_t> &packet) {
129 if (!mDeviceId.has_value()) {
130 BtsLog("hci_packet_transport: response with no device.");
131 return;
132 }
133 auto shared_packet = std::make_shared<std::vector<uint8_t>>(packet);
134 netsim::packet_hub::HandleBtResponse(mDeviceId.value(), packet_type,
135 shared_packet);
136 }
137
PacketTypeCallback(packet::HCIPacket_PacketType packet_type)138 rootcanal::PacketCallback HciPacketTransport::PacketTypeCallback(
139 packet::HCIPacket_PacketType packet_type) {
140 switch (packet_type) {
141 case HCIPacket::COMMAND:
142 assert(mCommandCallback);
143 return mCommandCallback;
144 case HCIPacket::ACL:
145 return mAclCallback;
146 case HCIPacket::SCO:
147 return mScoCallback;
148 case HCIPacket::ISO:
149 return mIsoCallback;
150 default:
151 BtsLog("hci_transport Ignoring unknown packet.");
152 return nullptr;
153 }
154 }
155
156 // handle_request is the main entry for incoming packets called by
157 // netsim::packet_hub
158 //
159 // Transfer the request to the HciTransport to deliver to Rootcanal via the
160 // acl/sco/iso/command callback methods under synchronization.
handle_bt_request(uint32_t facade_id,packet::HCIPacket_PacketType packet_type,const std::shared_ptr<std::vector<uint8_t>> & packet)161 void handle_bt_request(uint32_t facade_id,
162 packet::HCIPacket_PacketType packet_type,
163 const std::shared_ptr<std::vector<uint8_t>> &packet) {
164 if (device_to_transport_.find(facade_id) != device_to_transport_.end() &&
165 device_to_transport_[facade_id]) {
166 auto transport = device_to_transport_[facade_id];
167 transport->Request(packet_type, packet);
168 } else {
169 std::cout << "device_to_transport_ ids ";
170 for (auto [k, _] : device_to_transport_) std::cout << k << " ";
171 std::cout << std::endl;
172 BtsLog(
173 "hci_packet_transport: handle_request with no transport for device %d",
174 facade_id);
175 }
176 }
177
178 } // namespace hci
179 } // namespace netsim
180