}
void EnumGen::GenRustDef(std::ostream& stream) {
- stream << "#[derive(FromPrimitive, ToPrimitive)]\n";
+ stream << "#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]\n";
stream << "pub enum " << e_.name_ << " {";
for (const auto& pair : e_.constants_) {
stream << util::ConstantCaseToCamelCase(pair.second) << " = 0x" << std::hex << pair.first << std::dec << ",";
use num_traits::{FromPrimitive, ToPrimitive};
use std::convert::TryInto;
use thiserror::Error;
-use std::rc::Rc;
+use std::sync::Arc;
type Result<T> = std::result::Result<T, Error>;
void PacketDef::GenRustChildEnums(std::ostream& s) const {
if (!children_.empty()) {
+ s << "#[derive(Debug)] ";
s << "enum " << name_ << "DataChild {";
for (const auto& child : children_) {
- s << child->name_ << "(Rc<" << child->name_ << "Data>),";
+ s << child->name_ << "(Arc<" << child->name_ << "Data>),";
}
s << "None,";
s << "}\n";
+ s << "#[derive(Debug)] ";
s << "pub enum " << name_ << "Child {";
for (const auto& child : children_) {
s << child->name_ << "(" << child->name_ << "Packet),";
}
void PacketDef::GenRustStructDeclarations(std::ostream& s) const {
+ s << "#[derive(Debug)] ";
s << "struct " << name_ << "Data {";
// Generate struct fields
s << "}\n";
// Generate accessor struct
+ s << "#[derive(Debug, Clone)] ";
s << "pub struct " << name_ << "Packet {";
auto lineage = GetAncestors();
lineage.push_back(this);
for (auto it = lineage.begin(); it != lineage.end(); it++) {
auto def = *it;
- s << util::CamelCaseToUnderScore(def->name_) << ": Rc<" << def->name_ << "Data>,";
+ s << util::CamelCaseToUnderScore(def->name_) << ": Arc<" << def->name_ << "Data>,";
}
s << "}\n";
// Generate builder struct
+ s << "#[derive(Debug)] ";
s << "pub struct " << name_ << "Builder {";
auto params = GetParamList().GetFieldsWithoutTypes({
PayloadField::kFieldType,
s << "impl " << name_ << "Packet {";
if (parent_ == nullptr) {
s << "pub fn parse(bytes: &[u8]) -> Result<Self> { ";
- s << "Ok(Self::new(Rc::new(" << name_ << "Data::parse(bytes)?)))";
+ s << "Ok(Self::new(Arc::new(" << name_ << "Data::parse(bytes)?)))";
s << "}";
}
auto root = GetRootDef();
s << "}\n";
if (!children_.empty()) {
- s << " pub fn specialize(self) -> " << name_ << "Child {";
- s << " match self." << util::CamelCaseToUnderScore(name_) << ".child {";
+ s << " pub fn specialize(&self) -> " << name_ << "Child {";
+ s << " match &self." << util::CamelCaseToUnderScore(name_) << ".child {";
for (const auto& child : children_) {
s << name_ << "DataChild::" << child->name_ << "(_) => " << name_ << "Child::" << child->name_ << "("
- << child->name_ << "Packet::new(self." << root_accessor << ")),";
+ << child->name_ << "Packet::new(self." << root_accessor << ".clone())),";
}
s << name_ << "DataChild::None => " << name_ << "Child::None,";
s << "}}";
lineage.push_back(this);
const ParentDef* prev = nullptr;
- s << " fn new(root: Rc<" << root->name_ << "Data>) -> Self {";
+ s << " fn new(root: Arc<" << root->name_ << "Data>) -> Self {";
for (auto it = lineage.begin(); it != lineage.end(); it++) {
auto def = *it;
auto accessor_name = util::CamelCaseToUnderScore(def->name_);
});
auto accessor_name = util::CamelCaseToUnderScore(ancestor->name_);
- s << "let " << accessor_name << "= Rc::new(" << ancestor->name_ << "Data {";
+ s << "let " << accessor_name << "= Arc::new(" << ancestor->name_ << "Data {";
for (auto field : fields) {
auto constraint = all_constraints.find(field->GetName());
s << field->GetName() << ": ";
}
void StructDef::GenRustDeclarations(std::ostream& s) const {
+ s << "#[derive(Debug)] ";
s << "pub struct " << name_ << "{";
// Generate struct fields
srcs: ["src/lib.rs"],
edition: "2018",
rustlibs: [
- "libbt_packet",
"libbt_facade_proto",
+ "libbt_packets",
"libbytes",
"libfutures",
"libthiserror",
"liblazy_static",
"liblog_rust",
"libbt_common",
+ "libnum_traits",
+ ],
+ proc_macros: [
+ "libnum_derive",
],
target: {
android: {
use bt_facade_proto::common::Data;
use bt_facade_proto::empty::Empty;
use bt_facade_proto::hal_facade_grpc::{create_hci_hal_facade, HciHalFacade};
-use bt_packet::{HciCommand, HciEvent, RawPacket};
+use bt_packets::hci;
use futures::sink::SinkExt;
use gddi::{module, provides, Stoppable};
use grpcio::*;
#[derive(Clone, Stoppable)]
pub struct HciHalFacadeService {
rt: Arc<Runtime>,
- cmd_tx: mpsc::Sender<HciCommand>,
- evt_rx: Arc<Mutex<mpsc::Receiver<HciEvent>>>,
- acl_tx: mpsc::Sender<RawPacket>,
- acl_rx: Arc<Mutex<mpsc::Receiver<HciEvent>>>,
+ cmd_tx: mpsc::Sender<hci::CommandPacket>,
+ evt_rx: Arc<Mutex<mpsc::Receiver<hci::EventPacket>>>,
+ acl_tx: mpsc::Sender<hci::AclPacket>,
+ acl_rx: Arc<Mutex<mpsc::Receiver<hci::AclPacket>>>,
}
impl GrpcFacade for HciHalFacadeService {
fn send_command(&mut self, _ctx: RpcContext<'_>, mut data: Data, sink: UnarySink<Empty>) {
let cmd_tx = self.cmd_tx.clone();
self.rt.block_on(async move {
- cmd_tx.send(data.take_payload().into()).await.unwrap();
+ cmd_tx.send(hci::CommandPacket::parse(&data.take_payload()).unwrap()).await.unwrap();
});
sink.success(Empty::default());
}
fn send_acl(&mut self, _ctx: RpcContext<'_>, mut data: Data, sink: UnarySink<Empty>) {
let acl_tx = self.acl_tx.clone();
self.rt.block_on(async move {
- acl_tx.send(data.take_payload().into()).await.unwrap();
+ acl_tx.send(hci::AclPacket::parse(&data.take_payload()).unwrap()).await.unwrap();
});
sink.success(Empty::default());
}
self.rt.spawn(async move {
while let Some(event) = evt_rx.lock().await.recv().await {
let mut output = Data::default();
- output.set_payload(event.to_vec());
+ output.set_payload(event.to_bytes().to_vec());
sink.send((output, WriteFlags::default())).await.unwrap();
}
});
self.rt.spawn(async move {
while let Some(acl) = acl_rx.lock().await.recv().await {
let mut output = Data::default();
- output.set_payload(acl.to_vec());
+ output.set_payload(acl.to_bytes().to_vec());
sink.send((output, WriteFlags::default())).await.unwrap();
}
});
//! Implementation of the HAl that talks to BT controller over Android's HIDL
use crate::internal::{Hal, RawHalExports};
-use bt_packet::{HciCommand, HciEvent, RawPacket};
-use bytes::Bytes;
+use bt_packets::hci;
use gddi::{module, provides};
use std::sync::Arc;
use std::sync::Mutex;
struct Callbacks {
init_tx: UnboundedSender<()>,
- evt_tx: UnboundedSender<HciEvent>,
- acl_tx: UnboundedSender<RawPacket>,
+ evt_tx: UnboundedSender<hci::EventPacket>,
+ acl_tx: UnboundedSender<hci::AclPacket>,
}
lazy_static! {
.as_ref()
.unwrap()
.evt_tx
- .send(Bytes::copy_from_slice(data))
+ .send(hci::EventPacket::parse(data).unwrap())
.unwrap();
}
.as_ref()
.unwrap()
.acl_tx
- .send(Bytes::copy_from_slice(data))
+ .send(hci::AclPacket::parse(data).unwrap())
.unwrap();
}
fn on_sco(_data: &[u8]) {}
async fn dispatch_outgoing(
- mut cmd_rx: UnboundedReceiver<HciCommand>,
- mut acl_rx: UnboundedReceiver<RawPacket>,
+ mut cmd_rx: UnboundedReceiver<hci::CommandPacket>,
+ mut acl_rx: UnboundedReceiver<hci::AclPacket>,
) {
loop {
select! {
- Some(cmd) = cmd_rx.recv() => ffi::send_command(&cmd),
- Some(acl) = acl_rx.recv() => ffi::send_acl(&acl),
+ Some(cmd) = cmd_rx.recv() => ffi::send_command(&cmd.to_bytes()),
+ Some(acl) = acl_rx.recv() => ffi::send_acl(&acl.to_bytes()),
else => break,
}
}
#[cfg(target_os = "android")]
mod hidl_hal;
-use bt_packet::{HciCommand, HciEvent, RawPacket};
+use bt_packets::hci;
use gddi::{module, Stoppable};
use std::sync::Arc;
use thiserror::Error;
#[derive(Clone, Stoppable)]
pub struct HalExports {
/// Transmit end of a channel used to send HCI commands
- pub cmd_tx: Sender<HciCommand>,
+ pub cmd_tx: Sender<hci::CommandPacket>,
/// Receive end of a channel used to receive HCI events
- pub evt_rx: Arc<Mutex<Receiver<HciEvent>>>,
+ pub evt_rx: Arc<Mutex<Receiver<hci::EventPacket>>>,
/// Transmit end of a channel used to send ACL data
- pub acl_tx: Sender<RawPacket>,
+ pub acl_tx: Sender<hci::AclPacket>,
/// Receive end of a channel used to receive ACL data
- pub acl_rx: Arc<Mutex<Receiver<RawPacket>>>,
+ pub acl_rx: Arc<Mutex<Receiver<hci::AclPacket>>>,
}
mod internal {
- use bt_packet::{HciCommand, HciEvent, RawPacket};
+ use bt_packets::hci;
use gddi::Stoppable;
use std::sync::Arc;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
#[derive(Clone, Stoppable)]
pub struct RawHalExports {
- pub cmd_tx: UnboundedSender<HciCommand>,
- pub evt_rx: Arc<Mutex<UnboundedReceiver<HciEvent>>>,
- pub acl_tx: UnboundedSender<RawPacket>,
- pub acl_rx: Arc<Mutex<UnboundedReceiver<RawPacket>>>,
+ pub cmd_tx: UnboundedSender<hci::CommandPacket>,
+ pub evt_rx: Arc<Mutex<UnboundedReceiver<hci::EventPacket>>>,
+ pub acl_tx: UnboundedSender<hci::AclPacket>,
+ pub acl_rx: Arc<Mutex<UnboundedReceiver<hci::AclPacket>>>,
}
pub struct Hal {
- pub cmd_rx: UnboundedReceiver<HciCommand>,
- pub evt_tx: UnboundedSender<HciEvent>,
- pub acl_rx: UnboundedReceiver<RawPacket>,
- pub acl_tx: UnboundedSender<RawPacket>,
+ pub cmd_rx: UnboundedReceiver<hci::CommandPacket>,
+ pub evt_tx: UnboundedSender<hci::EventPacket>,
+ pub acl_rx: UnboundedReceiver<hci::AclPacket>,
+ pub acl_tx: UnboundedSender<hci::AclPacket>,
}
impl Hal {
use crate::internal::{Hal, RawHalExports};
use crate::{Result, H4_HEADER_SIZE};
-use bt_packet::{HciCommand, HciEvent, HciPacketHeaderSize, HciPacketType, RawPacket};
+use bt_packets::hci;
use bytes::{BufMut, Bytes, BytesMut};
use gddi::{module, provides, Stoppable};
use std::net::{IpAddr, SocketAddr};
use tokio::runtime::Runtime;
use tokio::select;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
+use num_derive::{FromPrimitive, ToPrimitive};
+
+#[derive(FromPrimitive, ToPrimitive)]
+enum HciPacketType {
+ Command = 0x01,
+ Acl = 0x02,
+ Sco = 0x03,
+ Event = 0x04,
+}
+
+#[derive(FromPrimitive, ToPrimitive)]
+enum HciPacketHeaderSize {
+ Event = 2,
+ Sco = 3,
+ Acl = 4,
+}
module! {
rootcanal_hal_module,
/// Send HCI events received from the HAL to the HCI layer
async fn dispatch_incoming<R>(
- evt_tx: UnboundedSender<HciEvent>,
- acl_tx: UnboundedSender<RawPacket>,
+ evt_tx: UnboundedSender<hci::EventPacket>,
+ acl_tx: UnboundedSender<hci::AclPacket>,
reader: R,
) -> Result<()>
where
payload.resize(len, 0);
reader.read_exact(&mut payload).await?;
buffer.unsplit(payload);
- evt_tx.send(buffer.freeze()).unwrap();
+ evt_tx.send(hci::EventPacket::parse(&buffer.freeze()).unwrap()).unwrap();
} else if buffer[0] == HciPacketType::Acl as u8 {
buffer.resize(HciPacketHeaderSize::Acl as usize, 0);
reader.read_exact(&mut buffer).await?;
payload.resize(len, 0);
reader.read_exact(&mut payload).await?;
buffer.unsplit(payload);
- acl_tx.send(buffer.freeze()).unwrap();
+ acl_tx.send(hci::AclPacket::parse(&buffer.freeze()).unwrap()).unwrap();
}
}
}
/// Send commands received from the HCI later to rootcanal
async fn dispatch_outgoing<W>(
- mut cmd_rx: UnboundedReceiver<HciCommand>,
- mut acl_rx: UnboundedReceiver<RawPacket>,
+ mut cmd_rx: UnboundedReceiver<hci::CommandPacket>,
+ mut acl_rx: UnboundedReceiver<hci::AclPacket>,
mut writer: W,
) -> Result<()>
where
{
loop {
select! {
- Some(cmd) = cmd_rx.recv() => write_with_type(&mut writer, HciPacketType::Command, cmd).await?,
- Some(acl) = acl_rx.recv() => write_with_type(&mut writer, HciPacketType::Acl, acl).await?,
+ Some(cmd) = cmd_rx.recv() => write_with_type(&mut writer, HciPacketType::Command, cmd.to_bytes()).await?,
+ Some(acl) = acl_rx.recv() => write_with_type(&mut writer, HciPacketType::Acl, acl.to_bytes()).await?,
else => break,
}
}
use crate::internal::RawHalExports;
use crate::HalExports;
use bt_common::sys_prop;
-use bt_packet::{HciCommand, HciEvent, RawPacket};
use bytes::{BufMut, Bytes, BytesMut};
use gddi::{module, provides, Stoppable};
use log::error;
use tokio::select;
use tokio::sync::mpsc::{channel, UnboundedReceiver};
use tokio::sync::Mutex;
+use bt_packets::hci;
/// The different modes snoop logging can be in
#[derive(Clone)]
hal_exports: RawHalExports,
rt: Arc<Runtime>,
) -> HalExports {
- let (cmd_down_tx, mut cmd_down_rx) = channel::<HciCommand>(10);
- let (evt_up_tx, evt_up_rx) = channel::<HciEvent>(10);
- let (acl_down_tx, mut acl_down_rx) = channel::<RawPacket>(10);
- let (acl_up_tx, acl_up_rx) = channel::<RawPacket>(10);
+ let (cmd_down_tx, mut cmd_down_rx) = channel::<hci::CommandPacket>(10);
+ let (evt_up_tx, evt_up_rx) = channel::<hci::EventPacket>(10);
+ let (acl_down_tx, mut acl_down_rx) = channel::<hci::AclPacket>(10);
+ let (acl_up_tx, acl_up_rx) = channel::<hci::AclPacket>(10);
rt.spawn(async move {
let mut logger = SnoopLogger::new(config).await;
select! {
Some(evt) = consume(&hal_exports.evt_rx) => {
evt_up_tx.send(evt.clone()).await.unwrap();
- logger.log(Type::Evt, Direction::Up, evt).await;
+ logger.log(Type::Evt, Direction::Up, evt.to_bytes()).await;
},
Some(cmd) = cmd_down_rx.recv() => {
hal_exports.cmd_tx.send(cmd.clone()).unwrap();
- logger.log(Type::Cmd, Direction::Down, cmd).await;
+ logger.log(Type::Cmd, Direction::Down, cmd.to_bytes()).await;
},
Some(acl) = acl_down_rx.recv() => {
hal_exports.acl_tx.send(acl.clone()).unwrap();
- logger.log(Type::Acl, Direction::Down, acl).await;
+ logger.log(Type::Acl, Direction::Down, acl.to_bytes()).await;
},
Some(acl) = consume(&hal_exports.acl_rx) => {
acl_up_tx.send(acl.clone()).await.unwrap();
- logger.log(Type::Acl, Direction::Up, acl).await;
+ logger.log(Type::Acl, Direction::Up, acl.to_bytes()).await;
}
}
}
rustlibs: [
"libbt_hal",
"libbt_facade_proto",
- "libbt_packet",
+ "libbt_packets",
"libbytes",
"libfutures",
"libgrpcio",
use bt_facade_proto::empty::Empty;
use bt_facade_proto::hci_facade::EventRequest;
use bt_facade_proto::hci_facade_grpc::{create_hci_layer_facade, HciLayerFacade};
-use bt_packet::HciEvent;
+use bt_packets::hci;
use futures::sink::SinkExt;
use gddi::{module, provides, Stoppable};
use grpcio::*;
use tokio::runtime::Runtime;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::Mutex;
+use num_traits::FromPrimitive;
module! {
facade_module,
#[provides]
async fn provide_facade(hci_exports: HciExports, rt: Arc<Runtime>) -> HciLayerFacadeService {
- let (from_hci_evt_tx, to_grpc_evt_rx) = channel::<HciEvent>(10);
+ let (from_hci_evt_tx, to_grpc_evt_rx) = channel::<hci::EventPacket>(10);
HciLayerFacadeService {
hci_exports,
rt,
pub struct HciLayerFacadeService {
hci_exports: HciExports,
rt: Arc<Runtime>,
- from_hci_evt_tx: Sender<HciEvent>,
- to_grpc_evt_rx: Arc<Mutex<Receiver<HciEvent>>>,
+ from_hci_evt_tx: Sender<hci::EventPacket>,
+ to_grpc_evt_rx: Arc<Mutex<Receiver<hci::EventPacket>>>,
}
impl GrpcFacade for HciLayerFacadeService {
mut data: Data,
sink: UnarySink<Empty>,
) {
- self.rt
- .block_on(self.hci_exports.enqueue_command_with_complete(data.take_payload().into()));
+ self.rt.block_on(
+ self.hci_exports
+ .enqueue_command_with_complete(hci::CommandPacket::parse(&data.take_payload()).unwrap()),
+ );
sink.success(Empty::default());
}
mut data: Data,
sink: UnarySink<Empty>,
) {
- self.rt
- .block_on(self.hci_exports.enqueue_command_with_complete(data.take_payload().into()));
+ self.rt.block_on(
+ self.hci_exports
+ .enqueue_command_with_complete(hci::CommandPacket::parse(&data.take_payload()).unwrap()),
+ );
sink.success(Empty::default());
}
fn request_event(&mut self, _ctx: RpcContext<'_>, code: EventRequest, sink: UnarySink<Empty>) {
self.rt.block_on(
self.hci_exports
- .register_event_handler(code.get_code() as u8, self.from_hci_evt_tx.clone()),
+ .register_event_handler(hci::EventCode::from_u32(code.get_code()).unwrap(), self.from_hci_evt_tx.clone()),
);
sink.success(Empty::default());
}
fn send_acl(&mut self, _ctx: RpcContext<'_>, mut packet: Data, sink: UnarySink<Empty>) {
let acl_tx = self.hci_exports.acl_tx.clone();
self.rt.block_on(async move {
- acl_tx.send(packet.take_payload().into()).await.unwrap();
+ acl_tx.send(hci::AclPacket::parse(&packet.take_payload()).unwrap()).await.unwrap();
});
sink.success(Empty::default());
}
self.rt.spawn(async move {
while let Some(event) = evt_rx.lock().await.recv().await {
let mut evt = Data::default();
- evt.set_payload(event.to_vec());
+ evt.set_payload(event.to_bytes().to_vec());
resp.send((evt, WriteFlags::default())).await.unwrap();
}
});
self.rt.spawn(async move {
while let Some(data) = acl_rx.lock().await.recv().await {
let mut packet = Data::default();
- packet.set_payload(data.to_vec());
+ packet.set_payload(data.to_bytes().to_vec());
resp.send((packet, WriteFlags::default())).await.unwrap();
}
});
pub mod facade;
use bt_hal::HalExports;
-use bt_packet::{HciCommand, HciEvent, RawPacket};
+use bt_packets::hci;
+use bt_packets::hci::EventChild::{CommandStatus,CommandComplete};
use error::Result;
use gddi::{module, provides, Stoppable};
use std::collections::HashMap;
/// to the command is received
#[derive(Debug)]
struct Command {
- cmd: HciCommand,
- fut: oneshot::Sender<HciCommand>,
+ cmd: hci::CommandPacket,
+ fut: oneshot::Sender<hci::EventPacket>,
}
#[derive(Debug)]
struct PendingCommand {
- opcode: u16,
- fut: oneshot::Sender<HciCommand>,
+ opcode: hci::OpCode,
+ fut: oneshot::Sender<hci::EventPacket>,
}
/// HCI interface
#[derive(Clone, Stoppable)]
pub struct HciExports {
cmd_tx: Sender<Command>,
- evt_handlers: Arc<Mutex<HashMap<u8, Sender<HciEvent>>>>,
+ evt_handlers: Arc<Mutex<HashMap<hci::EventCode, Sender<hci::EventPacket>>>>,
/// Transmit end of a channel used to send ACL data
- pub acl_tx: Sender<RawPacket>,
+ pub acl_tx: Sender<hci::AclPacket>,
/// Receive end of a channel used to receive ACL data
- pub acl_rx: Arc<Mutex<Receiver<RawPacket>>>,
+ pub acl_rx: Arc<Mutex<Receiver<hci::AclPacket>>>,
}
impl HciExports {
- async fn send(&mut self, cmd: HciCommand) -> Result<HciEvent> {
- let (tx, rx) = oneshot::channel::<HciEvent>();
+ async fn send(&mut self, cmd: hci::CommandPacket) -> Result<hci::EventPacket> {
+ let (tx, rx) = oneshot::channel::<hci::EventPacket>();
self.cmd_tx.send(Command { cmd, fut: tx }).await?;
let event = rx.await?;
Ok(event)
/// Enqueue an HCI command expecting a command complete
/// response from the controller
- pub async fn enqueue_command_with_complete(&mut self, cmd: HciCommand) -> HciEvent {
+ pub async fn enqueue_command_with_complete(&mut self, cmd: hci::CommandPacket) -> hci::EventPacket {
self.send(cmd).await.unwrap()
}
/// Enqueue an HCI command expecting a status response
/// from the controller
- pub async fn enqueue_command_with_status(&mut self, cmd: HciCommand) -> HciEvent {
+ pub async fn enqueue_command_with_status(&mut self, cmd: hci::CommandPacket) -> hci::EventPacket {
self.send(cmd).await.unwrap()
}
/// Indicate interest in specific HCI events
- pub async fn register_event_handler(&mut self, evt_code: u8, sender: Sender<HciEvent>) {
+ pub async fn register_event_handler(&mut self, evt_code: hci::EventCode, sender: Sender<hci::EventPacket>) {
self.evt_handlers.lock().await.insert(evt_code, sender);
}
}
async fn dispatch(
- evt_handlers: Arc<Mutex<HashMap<u8, Sender<HciEvent>>>>,
- evt_rx: Arc<Mutex<Receiver<HciEvent>>>,
- cmd_tx: Sender<HciCommand>,
+ evt_handlers: Arc<Mutex<HashMap<hci::EventCode, Sender<hci::EventPacket>>>>,
+ evt_rx: Arc<Mutex<Receiver<hci::EventPacket>>>,
+ cmd_tx: Sender<hci::CommandPacket>,
mut cmd_rx: Receiver<Command>,
) {
let mut pending_cmds: Vec<PendingCommand> = Vec::new();
loop {
select! {
Some(evt) = consume(&evt_rx) => {
- let opcode = bt_packet::get_evt_opcode(&evt).unwrap();
- let evt_code = bt_packet::get_evt_code(&evt).unwrap();
- if let Some(pending_cmd) = remove_first(&mut pending_cmds, |entry| entry.opcode == opcode) {
- pending_cmd.fut.send(evt).unwrap();
- } else if let Some(sender) = evt_handlers.lock().await.get(&evt_code) {
- sender.send(evt).await.unwrap();
+ match evt.specialize() {
+ CommandStatus(evt) => {
+ let opcode = *evt.get_command_op_code();
+ if let Some(pending_cmd) = remove_first(&mut pending_cmds, |entry| entry.opcode == opcode) {
+ pending_cmd.fut.send(evt.into()).unwrap();
+ }
+ },
+ CommandComplete(evt) => {
+ let opcode = *evt.get_command_op_code();
+ if let Some(pending_cmd) = remove_first(&mut pending_cmds, |entry| entry.opcode == opcode) {
+ pending_cmd.fut.send(evt.into()).unwrap();
+ }
+ },
+ _ => {
+ if let Some(sender) = evt_handlers.lock().await.get(evt.get_event_code()) {
+ sender.send(evt).await.unwrap();
+ }
+ },
}
},
Some(cmd) = cmd_rx.recv() => {
pending_cmds.push(PendingCommand {
- opcode: bt_packet::get_cmd_opcode(&cmd.cmd).unwrap(),
+ opcode: *cmd.cmd.get_op_code(),
fut: cmd.fut,
});
cmd_tx.send(cmd.cmd).await.unwrap();
}
}
-async fn consume(evt_rx: &Arc<Mutex<Receiver<HciEvent>>>) -> Option<HciEvent> {
+async fn consume(evt_rx: &Arc<Mutex<Receiver<hci::EventPacket>>>) -> Option<hci::EventPacket> {
evt_rx.lock().await.recv().await
}
+++ /dev/null
-rust_library {
- name: "libbt_packet",
- defaults: ["gd_rust_defaults"],
- // has rustc warnings
- crate_name: "bt_packet",
- srcs: ["src/lib.rs"],
- edition: "2018",
- rustlibs: [
- "libbytes",
- "libnum_traits",
- ],
- proc_macros: [
- "libnum_derive",
- ],
-}
+++ /dev/null
-//! HCI packet representation
-//! This is temporary and will be replaced by a shim that uses
-//! existing C++ packet code through CXX
-
-use bytes::Bytes;
-use num_derive::{FromPrimitive, ToPrimitive};
-
-/// Packet types
-#[derive(FromPrimitive, ToPrimitive)]
-pub enum HciPacketType {
- /// HCI command packet
- Command = 0x01,
- /// ACL data packet
- Acl = 0x02,
- /// SCO data packet
- Sco = 0x03,
- /// HCI event packet
- Event = 0x04,
-}
-
-/// Header size (in bytes) for each packet type
-#[derive(FromPrimitive, ToPrimitive)]
-pub enum HciPacketHeaderSize {
- /// HCI Event packet header size
- Event = 2,
- /// SCO packet header size
- Sco = 3,
- /// ACL packet header size
- Acl = 4,
-}
-
-/// Raw packet
-pub type RawPacket = Bytes;
-
-/// HCI command packet
-pub type HciCommand = Bytes;
-
-/// Gets the 16-bit opcode for an HCI command
-pub fn get_cmd_opcode(cmd: &HciCommand) -> Option<u16> {
- let b0 = ((cmd[0] as u16) << 8) as u16;
- let b1 = (cmd[1] as u16) as u16;
- Some(b0 | b1)
-}
-
-/// HCI event packet
-pub type HciEvent = Bytes;
-
-/// Gets the HCI command opcode corresponding to an event
-pub fn get_evt_opcode(event: &HciEvent) -> Option<u16> {
- let b0 = ((event[3] as u16) << 8) as u16;
- let b1 = (event[4] as u16) as u16;
- Some(b0 | b1)
-}
-
-/// Gets the event code for an HCI event
-pub fn get_evt_code(event: &HciEvent) -> Option<u8> {
- Some(event[0])
-}
-
-/// Packet bytes for each packet type
-#[derive(Debug)]
-pub enum HciPacket {
- /// HCI command
- Command(HciCommand),
- /// ACL packet
- Acl(RawPacket),
- /// SCO packet
- Sco(RawPacket),
- /// HCI event
- Event(HciEvent),
-}