• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC
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 //     https://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 //! Netsim daemon cxx libraries.
16 
17 use crate::bluetooth::chip::{
18     create_add_rust_device_result, AddRustDeviceResult, RustBluetoothChipCallbacks,
19 };
20 
21 use crate::devices::devices_handler::get_distance_cxx;
22 use crate::ranging::*;
23 use crate::wireless::{
24     bluetooth::report_invalid_packet_cxx, handle_request_cxx, handle_response_cxx,
25 };
26 
27 #[allow(unsafe_op_in_unsafe_fn)]
28 #[cxx::bridge(namespace = "netsim::wireless")]
29 pub mod ffi_wireless {
30     extern "Rust" {
31         #[cxx_name = HandleRequestCxx]
handle_request_cxx(chip_id: u32, packet: &CxxVector<u8>, packet_type: u8)32         fn handle_request_cxx(chip_id: u32, packet: &CxxVector<u8>, packet_type: u8);
33 
34         #[cxx_name = HandleResponse]
handle_response_cxx(chip_id: u32, packet: &CxxVector<u8>, packet_type: u8)35         fn handle_response_cxx(chip_id: u32, packet: &CxxVector<u8>, packet_type: u8);
36     }
37 }
38 
39 #[allow(unsafe_op_in_unsafe_fn)]
40 #[cxx::bridge(namespace = "netsim::transport")]
41 pub mod ffi_transport {
42     unsafe extern "C++" {
43         // Grpc client.
44         // Expose functions in Cuttlefish only, because it's only used by CVDs and it's
45         // unable to pass function pointers on Windows.
46         #[cfg(feature = "cuttlefish")]
47         include!("backend/grpc_client.h");
48 
49         #[allow(dead_code)]
50         #[rust_name = stream_packets]
51         #[namespace = "netsim::backend::client"]
52         #[cfg(feature = "cuttlefish")]
StreamPackets(server: &String) -> u3253         fn StreamPackets(server: &String) -> u32;
54 
55         #[allow(dead_code)]
56         #[rust_name = read_packet_response_loop]
57         #[namespace = "netsim::backend::client"]
58         #[cfg(feature = "cuttlefish")]
ReadPacketResponseLoop( stream_id: u32, read_fn: fn(stream_id: u32, proto_bytes: &[u8]), ) -> bool59         fn ReadPacketResponseLoop(
60             stream_id: u32,
61             read_fn: fn(stream_id: u32, proto_bytes: &[u8]),
62         ) -> bool;
63 
64         #[allow(dead_code)]
65         #[rust_name = write_packet_request]
66         #[cfg(feature = "cuttlefish")]
67         #[namespace = "netsim::backend::client"]
WritePacketRequest(stream_id: u32, proto_bytes: &[u8]) -> bool68         fn WritePacketRequest(stream_id: u32, proto_bytes: &[u8]) -> bool;
69 
70     }
71 }
72 
73 #[allow(clippy::needless_maybe_sized)]
74 #[allow(unsafe_op_in_unsafe_fn)]
75 #[cxx::bridge(namespace = "netsim")]
76 pub mod ffi_bluetooth {
77     extern "Rust" {
78         // Rust Bluetooth device.
79         #[namespace = "netsim::hci::facade"]
80         type DynRustBluetoothChipCallbacks;
81 
82         #[cxx_name = Tick]
83         #[namespace = "netsim::hci::facade"]
tick(dyn_callbacks: &mut DynRustBluetoothChipCallbacks)84         fn tick(dyn_callbacks: &mut DynRustBluetoothChipCallbacks);
85 
86         #[cxx_name = ReceiveLinkLayerPacket]
87         #[namespace = "netsim::hci::facade"]
receive_link_layer_packet( dyn_callbacks: &mut DynRustBluetoothChipCallbacks, source_address: String, destination_address: String, packet_type: u8, packet: &[u8], )88         fn receive_link_layer_packet(
89             dyn_callbacks: &mut DynRustBluetoothChipCallbacks,
90             source_address: String,
91             destination_address: String,
92             packet_type: u8,
93             packet: &[u8],
94         );
95 
96         // Bluetooth facade.
97         #[namespace = "netsim::hci::facade"]
98         type AddRustDeviceResult;
99         #[cxx_name = "CreateAddRustDeviceResult"]
100         #[namespace = "netsim::hci"]
create_add_rust_device_result( facade_id: u32, rust_chip: UniquePtr<RustBluetoothChip>, ) -> Box<AddRustDeviceResult>101         fn create_add_rust_device_result(
102             facade_id: u32,
103             rust_chip: UniquePtr<RustBluetoothChip>,
104         ) -> Box<AddRustDeviceResult>;
105 
106         // Rust Invalid Packet Report
107         #[cxx_name = "ReportInvalidPacket"]
108         #[namespace = "netsim::hci::facade"]
report_invalid_packet_cxx( rootcanal_id: u32, reason: i32, description: &CxxString, packet: &CxxVector<u8>, )109         fn report_invalid_packet_cxx(
110             rootcanal_id: u32,
111             reason: i32,
112             description: &CxxString,
113             packet: &CxxVector<u8>,
114         );
115     }
116 
117     #[allow(dead_code)]
118     unsafe extern "C++" {
119         // Bluetooth facade.
120         include!("hci/hci_packet_hub.h");
121 
122         #[rust_name = handle_bt_request]
123         #[namespace = "netsim::hci"]
HandleBtRequestCxx(rootcanal_id: u32, packet_type: u8, packet: &Vec<u8>)124         fn HandleBtRequestCxx(rootcanal_id: u32, packet_type: u8, packet: &Vec<u8>);
125 
126         // Rust Bluetooth device.
127         include!("hci/rust_device.h");
128 
129         #[namespace = "netsim::hci::facade"]
130         type RustBluetoothChip;
131         #[rust_name = send_link_layer_le_packet]
132         #[namespace = "netsim::hci::facade"]
SendLinkLayerLePacket(self: &RustBluetoothChip, packet: &[u8], tx_power: i8)133         fn SendLinkLayerLePacket(self: &RustBluetoothChip, packet: &[u8], tx_power: i8);
134 
135         include!("hci/bluetooth_facade.h");
136 
137         #[rust_name = bluetooth_get_cxx]
138         #[namespace = "netsim::hci::facade"]
GetCxx(rootcanal_id: u32) -> Vec<u8>139         pub fn GetCxx(rootcanal_id: u32) -> Vec<u8>;
140 
141         #[rust_name = bluetooth_reset]
142         #[namespace = "netsim::hci::facade"]
Reset(rootcanal_id: u32)143         pub fn Reset(rootcanal_id: u32);
144 
145         #[rust_name = bluetooth_remove]
146         #[namespace = "netsim::hci::facade"]
Remove(rootcanal_id: u32)147         pub fn Remove(rootcanal_id: u32);
148 
149         #[rust_name = bluetooth_add]
150         #[namespace = "netsim::hci::facade"]
Add(chip_id: u32, address: &CxxString, controller_proto_bytes: &[u8]) -> u32151         pub fn Add(chip_id: u32, address: &CxxString, controller_proto_bytes: &[u8]) -> u32;
152 
153         /*
154         From https://cxx.rs/binding/box.html#restrictions,
155         ```
156         If T is an opaque Rust type, the Rust type is required to be Sized i.e. size known at compile time. In the future we may introduce support for dynamically sized opaque Rust types.
157         ```
158 
159         The workaround is using Box<dyn MyData> (fat pointer) as the opaque type.
160         Reference:
161         - Passing trait objects to C++. https://github.com/dtolnay/cxx/issues/665.
162         - Exposing trait methods to C++. https://github.com/dtolnay/cxx/issues/667
163                 */
164         #[rust_name = bluetooth_add_rust_device]
165         #[namespace = "netsim::hci::facade"]
AddRustDevice( chip_id: u32, callbacks: Box<DynRustBluetoothChipCallbacks>, string_type: &CxxString, address: &CxxString, ) -> Box<AddRustDeviceResult>166         pub fn AddRustDevice(
167             chip_id: u32,
168             callbacks: Box<DynRustBluetoothChipCallbacks>,
169             string_type: &CxxString,
170             address: &CxxString,
171         ) -> Box<AddRustDeviceResult>;
172 
173         /// The provided address must be 6 bytes in length
174         #[rust_name = bluetooth_set_rust_device_address]
175         #[namespace = "netsim::hci::facade"]
SetRustDeviceAddress(rootcanal_id: u32, address: [u8; 6])176         pub fn SetRustDeviceAddress(rootcanal_id: u32, address: [u8; 6]);
177 
178         #[rust_name = bluetooth_remove_rust_device]
179         #[namespace = "netsim::hci::facade"]
RemoveRustDevice(rootcanal_id: u32)180         pub fn RemoveRustDevice(rootcanal_id: u32);
181 
182         #[rust_name = bluetooth_start]
183         #[namespace = "netsim::hci::facade"]
Start(proto_bytes: &[u8], instance_num: u16)184         pub fn Start(proto_bytes: &[u8], instance_num: u16);
185 
186         #[rust_name = bluetooth_stop]
187         #[namespace = "netsim::hci::facade"]
Stop()188         pub fn Stop();
189 
190         #[rust_name = add_device_to_phy]
191         #[namespace = "netsim::hci::facade"]
AddDeviceToPhy(rootcanal_id: u32, is_low_energy: bool)192         pub fn AddDeviceToPhy(rootcanal_id: u32, is_low_energy: bool);
193 
194         #[rust_name = remove_device_from_phy]
195         #[namespace = "netsim::hci::facade"]
RemoveDeviceFromPhy(rootcanal_id: u32, is_low_energy: bool)196         pub fn RemoveDeviceFromPhy(rootcanal_id: u32, is_low_energy: bool);
197     }
198 }
199 
200 #[allow(clippy::needless_maybe_sized)]
201 #[allow(unsafe_op_in_unsafe_fn)]
202 #[cxx::bridge(namespace = "netsim::device")]
203 pub mod ffi_devices {
204     extern "Rust" {
205         #[cxx_name = GetDistanceCxx]
get_distance_cxx(a: u32, b: u32) -> f32206         fn get_distance_cxx(a: u32, b: u32) -> f32;
207     }
208 }
209 
210 #[allow(unsafe_op_in_unsafe_fn)]
211 #[cxx::bridge(namespace = "netsim")]
212 pub mod ffi_util {
213     extern "Rust" {
214         // Ranging
215 
216         #[cxx_name = "DistanceToRssi"]
distance_to_rssi(tx_power: i8, distance: f32) -> i8217         fn distance_to_rssi(tx_power: i8, distance: f32) -> i8;
218     }
219 
220     #[allow(dead_code)]
221     unsafe extern "C++" {
222 
223         // Crash report.
224         include!("util/crash_report.h");
225 
226         #[rust_name = set_up_crash_report]
227         #[namespace = "netsim"]
SetUpCrashReport()228         pub fn SetUpCrashReport();
229     }
230 }
231 
232 // It's required so `RustBluetoothChip` can be sent between threads safely.
233 // Ref: How to use opaque types in threads? https://github.com/dtolnay/cxx/issues/1175
234 // SAFETY: Nothing in `RustBluetoothChip` depends on being run on a particular thread.
235 unsafe impl Send for ffi_bluetooth::RustBluetoothChip {}
236 
237 type DynRustBluetoothChipCallbacks = Box<dyn RustBluetoothChipCallbacks>;
238 
tick(dyn_callbacks: &mut DynRustBluetoothChipCallbacks)239 fn tick(dyn_callbacks: &mut DynRustBluetoothChipCallbacks) {
240     (**dyn_callbacks).tick();
241 }
242 
receive_link_layer_packet( dyn_callbacks: &mut DynRustBluetoothChipCallbacks, source_address: String, destination_address: String, packet_type: u8, packet: &[u8], )243 fn receive_link_layer_packet(
244     dyn_callbacks: &mut DynRustBluetoothChipCallbacks,
245     source_address: String,
246     destination_address: String,
247     packet_type: u8,
248     packet: &[u8],
249 ) {
250     (**dyn_callbacks).receive_link_layer_packet(
251         source_address,
252         destination_address,
253         packet_type,
254         packet,
255     );
256 }
257