// Copyright 2023 The Android Open Source Project // // 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 // // http://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 std::cell::{Cell, RefCell}; use std::collections::VecDeque; use std::convert::{TryFrom, TryInto}; use std::future::Future; use std::pin::Pin; use std::rc::{Rc, Weak}; use std::task::{Context, Poll};
use pdl_runtime::Packet as _; use thiserror::Error;
struct Link {
peer: Cell<hci::Address>, // Only store one HCI packet as our Num_HCI_Command_Packets // is always 1
hci: Cell<Option<hci::Command>>,
lmp: RefCell<VecDeque<lmp::LmpPacket>>,
}
impl Default for Link { fn default() -> Self {
Link {
peer: Cell::new(hci::EMPTY_ADDRESS),
hci: Default::default(),
lmp: Default::default(),
}
}
}
impl Link { fn ingest_lmp(&self, packet: lmp::LmpPacket) { self.lmp.borrow_mut().push_back(packet);
}
/// Send a command complete or command status event /// with the specified error code. fn send_command_complete_event(
&self,
command: &hci::Command,
status: hci::ErrorCode,
) -> Result<(), LinkManagerError> { use hci::CommandChild::*;
pubfn ingest_hci(&self, command: hci::Command) -> Result<(), LinkManagerError> { // Try to find the matching link from the command arguments let link = hci::command_connection_handle(&command)
.and_then(|handle| self.ops.get_address(handle))
.or_else(|| hci::command_remote_device_address(&command))
.and_then(|peer| self.get_link(peer));
pubfn add_link(self: &Rc<Self>, peer: hci::Address) -> Result<(), LinkManagerError> { let index = self
.links
.iter()
.position(|link| link.peer.get().is_empty());
iflet Some(index) = index { self.links[index].peer.set(peer); let context = LinkContext { index: index as u8, manager: Rc::downgrade(self) }; self.procedures.borrow_mut()[index] = Some(Box::pin(procedure::run(context)));
Ok(())
} else {
Err(LinkManagerError::UnhandledHciPacket)
}
}
pubfn remove_link(&self, peer: hci::Address) -> Result<(), LinkManagerError> { let index = self.links.iter().position(|link| link.peer.get() == peer);
iflet Some(index) = index { // Send HCI command complete or status event for the pending HCI comamnd // if any. Failing to do that would break flow control expectations for the host. iflet Some(command) = self.links[index].hci.replace(None) { self.send_command_complete_event(&command, hci::ErrorCode::UnknownConnection)?;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.