1 //! Rootcanal HAL
2 //! This connects to "rootcanal" which provides a simulated
3 //! Bluetooth chip as well as a simulated environment.
4
5 use crate::internal::{InnerHal, RawHal};
6 use crate::{Result, H4_HEADER_SIZE};
7 use bt_packets::hci::{AclPacket, CommandPacket, EventPacket, IsoPacket, Packet};
8 use bytes::{BufMut, Bytes, BytesMut};
9 use gddi::{module, provides, Stoppable};
10 use num_derive::{FromPrimitive, ToPrimitive};
11 use std::net::{IpAddr, SocketAddr};
12 use std::str::FromStr;
13 use std::sync::Arc;
14 use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader};
15 use tokio::net::TcpStream;
16 use tokio::runtime::Runtime;
17 use tokio::select;
18 use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
19
20 #[derive(FromPrimitive, ToPrimitive)]
21 enum HciPacketType {
22 Command = 0x01,
23 Acl = 0x02,
24 Sco = 0x03,
25 Event = 0x04,
26 Iso = 0x05,
27 }
28
29 const SIZE_OF_EVENT_HEADER: usize = 2;
30 const _SIZE_OF_SCO_HEADER: usize = 3;
31 const SIZE_OF_ACL_HEADER: usize = 4;
32 const SIZE_OF_ISO_HEADER: usize = 4;
33
34 module! {
35 rootcanal_hal_module,
36 providers {
37 RawHal => provide_rootcanal_hal,
38 }
39 }
40
41 #[provides]
provide_rootcanal_hal(config: RootcanalConfig, rt: Arc<Runtime>) -> RawHal42 async fn provide_rootcanal_hal(config: RootcanalConfig, rt: Arc<Runtime>) -> RawHal {
43 let (raw_hal, inner_hal) = InnerHal::new();
44 let (reader, writer) = TcpStream::connect(&config.to_socket_addr().unwrap())
45 .await
46 .expect("unable to create stream to rootcanal")
47 .into_split();
48
49 rt.spawn(dispatch_incoming(inner_hal.evt_tx, inner_hal.acl_tx, inner_hal.iso_tx, reader));
50 rt.spawn(dispatch_outgoing(inner_hal.cmd_rx, inner_hal.acl_rx, inner_hal.iso_rx, writer));
51
52 raw_hal
53 }
54
55 /// Rootcanal configuration
56 #[derive(Clone, Debug, Default, Stoppable)]
57 pub struct RootcanalConfig {
58 address: String,
59 port: u16,
60 }
61
62 impl RootcanalConfig {
63 /// Create a rootcanal config
new(address: &str, port: u16) -> Self64 pub fn new(address: &str, port: u16) -> Self {
65 Self { address: String::from(address), port }
66 }
67
to_socket_addr(&self) -> Result<SocketAddr>68 fn to_socket_addr(&self) -> Result<SocketAddr> {
69 Ok(SocketAddr::new(IpAddr::from_str(&self.address)?, self.port))
70 }
71 }
72
73 /// Send HCI events received from the HAL to the HCI layer
dispatch_incoming<R>( evt_tx: UnboundedSender<EventPacket>, acl_tx: UnboundedSender<AclPacket>, iso_tx: UnboundedSender<IsoPacket>, reader: R, ) -> Result<()> where R: AsyncReadExt + Unpin,74 async fn dispatch_incoming<R>(
75 evt_tx: UnboundedSender<EventPacket>,
76 acl_tx: UnboundedSender<AclPacket>,
77 iso_tx: UnboundedSender<IsoPacket>,
78 reader: R,
79 ) -> Result<()>
80 where
81 R: AsyncReadExt + Unpin,
82 {
83 let mut reader = BufReader::new(reader);
84 loop {
85 let mut buffer = BytesMut::with_capacity(1024);
86 buffer.resize(H4_HEADER_SIZE, 0);
87 reader.read_exact(&mut buffer).await?;
88 if buffer[0] == HciPacketType::Event as u8 {
89 buffer.resize(SIZE_OF_EVENT_HEADER, 0);
90 reader.read_exact(&mut buffer).await?;
91 let len: usize = buffer[1].into();
92 let mut payload = buffer.split_off(SIZE_OF_EVENT_HEADER);
93 payload.resize(len, 0);
94 reader.read_exact(&mut payload).await?;
95 buffer.unsplit(payload);
96 let frozen = buffer.freeze();
97 match EventPacket::parse(&frozen) {
98 Ok(p) => evt_tx.send(p).unwrap(),
99 Err(e) => log::error!("dropping invalid event packet: {}: {:02x}", e, frozen),
100 }
101 } else if buffer[0] == HciPacketType::Acl as u8 {
102 buffer.resize(SIZE_OF_ACL_HEADER, 0);
103 reader.read_exact(&mut buffer).await?;
104 let len: usize = (buffer[2] as u16 + ((buffer[3] as u16) << 8)).into();
105 let mut payload = buffer.split_off(SIZE_OF_ACL_HEADER);
106 payload.resize(len, 0);
107 reader.read_exact(&mut payload).await?;
108 buffer.unsplit(payload);
109 let frozen = buffer.freeze();
110 match AclPacket::parse(&frozen) {
111 Ok(p) => acl_tx.send(p).unwrap(),
112 Err(e) => log::error!("dropping invalid ACL packet: {}: {:02x}", e, frozen),
113 }
114 } else if buffer[0] == HciPacketType::Iso as u8 {
115 buffer.resize(SIZE_OF_ISO_HEADER, 0);
116 reader.read_exact(&mut buffer).await?;
117 let len: usize = (buffer[2] as u16 + (((buffer[3] & 0x3f) as u16) << 8)).into();
118 let mut payload = buffer.split_off(SIZE_OF_ISO_HEADER);
119 payload.resize(len, 0);
120 reader.read_exact(&mut payload).await?;
121 buffer.unsplit(payload);
122 let frozen = buffer.freeze();
123 match IsoPacket::parse(&frozen) {
124 Ok(p) => iso_tx.send(p).unwrap(),
125 Err(e) => log::error!("dropping invalid ISO packet: {}: {:02x}", e, frozen),
126 }
127 }
128 }
129 }
130
131 /// Send commands received from the HCI later to rootcanal
dispatch_outgoing<W>( mut cmd_rx: UnboundedReceiver<CommandPacket>, mut acl_rx: UnboundedReceiver<AclPacket>, mut iso_rx: UnboundedReceiver<IsoPacket>, mut writer: W, ) -> Result<()> where W: AsyncWriteExt + Unpin,132 async fn dispatch_outgoing<W>(
133 mut cmd_rx: UnboundedReceiver<CommandPacket>,
134 mut acl_rx: UnboundedReceiver<AclPacket>,
135 mut iso_rx: UnboundedReceiver<IsoPacket>,
136 mut writer: W,
137 ) -> Result<()>
138 where
139 W: AsyncWriteExt + Unpin,
140 {
141 loop {
142 select! {
143 Some(cmd) = cmd_rx.recv() => write_with_type(&mut writer, HciPacketType::Command, cmd.to_bytes()).await?,
144 Some(acl) = acl_rx.recv() => write_with_type(&mut writer, HciPacketType::Acl, acl.to_bytes()).await?,
145 Some(iso) = iso_rx.recv() => write_with_type(&mut writer, HciPacketType::Iso, iso.to_bytes()).await?,
146 else => break,
147 }
148 }
149
150 Ok(())
151 }
152
write_with_type<W>(writer: &mut W, t: HciPacketType, b: Bytes) -> Result<()> where W: AsyncWriteExt + Unpin,153 async fn write_with_type<W>(writer: &mut W, t: HciPacketType, b: Bytes) -> Result<()>
154 where
155 W: AsyncWriteExt + Unpin,
156 {
157 let mut data = BytesMut::with_capacity(b.len() + 1);
158 data.put_u8(t as u8);
159 data.extend(b);
160 writer.write_all(&data[..]).await?;
161
162 Ok(())
163 }
164