blob: 509d56615ec2d6157c7a68187d368f51731173fc [file] [log] [blame]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::devices::chip::FacadeIdentifier;
use crate::ffi::ffi_bluetooth;
use crate::{devices::device::DeviceIdentifier, echip::EmulatedChip};
use cxx::let_cxx_string;
use netsim_proto::common::ChipKind as ProtoChipKind;
use netsim_proto::config::Bluetooth as BluetoothConfig;
use netsim_proto::configuration::Controller as RootcanalController;
use netsim_proto::model::chip::Bluetooth as ProtoBluetooth;
use netsim_proto::model::Chip as ProtoChip;
use protobuf::{Message, MessageField};
use std::rc::Rc;
/// Parameters for creating Bluetooth chips
pub struct CreateParams {
device_id: DeviceIdentifier,
address: String,
bt_properties: MessageField<RootcanalController>,
}
/// Bluetooth struct will keep track of facade_id
pub struct Bluetooth {
facade_id: FacadeIdentifier,
}
impl EmulatedChip for Bluetooth {
fn handle_request(&self, packet: &[u8]) {
ffi_bluetooth::handle_bt_request(self.facade_id, packet[0], &packet[1..].to_vec())
}
fn reset(&self) {
ffi_bluetooth::bluetooth_reset(self.facade_id);
}
fn get(&self) -> ProtoChip {
let bluetooth_bytes = ffi_bluetooth::bluetooth_get_cxx(self.facade_id);
let bt_proto = ProtoBluetooth::parse_from_bytes(&bluetooth_bytes).unwrap();
let mut chip_proto = ProtoChip::new();
chip_proto.mut_bt().clone_from(&bt_proto);
chip_proto
}
fn patch(&self, chip: ProtoChip) {
let bluetooth_bytes = chip.bt().write_to_bytes().unwrap();
ffi_bluetooth::bluetooth_patch_cxx(self.facade_id, &bluetooth_bytes);
}
fn get_kind(&self) -> ProtoChipKind {
ProtoChipKind::BLUETOOTH
}
}
impl Drop for Bluetooth {
/// At drop, Remove the emulated chip from the virtual device. No further calls will
/// be made on this emulated chip. This is called when the packet stream from
/// the virtual device closes.
fn drop(&mut self) {
ffi_bluetooth::bluetooth_remove(self.facade_id);
}
}
/// Create a new Emulated Bluetooth Chip
pub fn new(create_params: CreateParams) -> Rc<dyn EmulatedChip> {
let_cxx_string!(cxx_address = create_params.address);
let proto_bytes =
create_params.bt_properties.as_ref().unwrap_or_default().write_to_bytes().unwrap();
let facade_id =
ffi_bluetooth::bluetooth_add(create_params.device_id, &cxx_address, &proto_bytes);
let echip = Bluetooth { facade_id };
Rc::new(echip)
}
/// Starts the Bluetooth service.
pub fn bluetooth_start(
config: &MessageField<BluetoothConfig>,
instance_num: u16,
disable_address_reuse: bool,
) {
let proto_bytes = config.as_ref().unwrap_or_default().write_to_bytes().unwrap();
ffi_bluetooth::bluetooth_start(&proto_bytes, instance_num, disable_address_reuse);
}
/// Stops the Bluetooth service.
pub fn bluetooth_stop() {
ffi_bluetooth::bluetooth_stop();
}