• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021, The Android Open Source Project
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 //     http://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 //! Rootcanal HAL
16 //! This connects to "rootcanal" which provides a simulated
17 //! Nfc chip as well as a simulated environment.
18 
19 use crate::internal::InnerHal;
20 use crate::{is_control_packet, Hal, HalEvent, HalEventRegistry, HalEventStatus, Result};
21 use bytes::{BufMut, BytesMut};
22 use log::{debug, error};
23 use nfc_packets::nci::{DataPacket, NciPacket, Packet};
24 use std::convert::TryInto;
25 use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader};
26 use tokio::net::TcpStream;
27 use tokio::select;
28 use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
29 
30 /// Initialize the module
init() -> Hal31 pub async fn init() -> Hal {
32     let (raw_hal, inner_hal) = InnerHal::new();
33     let (reader, writer) = TcpStream::connect("127.0.0.1:54323")
34         .await
35         .expect("unable to create stream to rootcanal")
36         .into_split();
37 
38     let reader = BufReader::new(reader);
39     tokio::spawn(dispatch_incoming(inner_hal.in_cmd_tx, inner_hal.in_data_tx, reader));
40     tokio::spawn(dispatch_outgoing(
41         raw_hal.hal_events.clone(),
42         inner_hal.out_cmd_rx,
43         inner_hal.out_data_rx,
44         writer,
45     ));
46 
47     raw_hal
48 }
49 
50 /// Send NCI events received from the HAL to the NCI layer
dispatch_incoming<R>( in_cmd_tx: UnboundedSender<NciPacket>, in_data_tx: UnboundedSender<DataPacket>, mut reader: R, ) -> Result<()> where R: AsyncReadExt + Unpin,51 async fn dispatch_incoming<R>(
52     in_cmd_tx: UnboundedSender<NciPacket>,
53     in_data_tx: UnboundedSender<DataPacket>,
54     mut reader: R,
55 ) -> Result<()>
56 where
57     R: AsyncReadExt + Unpin,
58 {
59     loop {
60         let mut buffer = BytesMut::with_capacity(1024);
61         let len: usize = reader.read_u16().await?.into();
62         buffer.resize(len, 0);
63         reader.read_exact(&mut buffer).await?;
64         let frozen = buffer.freeze();
65         debug!("{:?}", &frozen);
66         if is_control_packet(&frozen[..]) {
67             match NciPacket::parse(&frozen) {
68                 Ok(p) => {
69                     if in_cmd_tx.send(p).is_err() {
70                         break;
71                     }
72                 }
73                 Err(e) => error!("dropping invalid cmd event packet: {}: {:02x}", e, frozen),
74             }
75         } else {
76             match DataPacket::parse(&frozen) {
77                 Ok(p) => {
78                     if in_data_tx.send(p).is_err() {
79                         break;
80                     }
81                 }
82                 Err(e) => error!("dropping invalid data event packet: {}: {:02x}", e, frozen),
83             }
84         }
85     }
86     debug!("Dispatch incoming finished.");
87     Ok(())
88 }
89 
90 /// Send commands received from the NCI later to rootcanal
dispatch_outgoing<W>( mut hal_events: HalEventRegistry, mut out_cmd_rx: UnboundedReceiver<NciPacket>, mut out_data_rx: UnboundedReceiver<DataPacket>, mut writer: W, ) -> Result<()> where W: AsyncWriteExt + Unpin,91 async fn dispatch_outgoing<W>(
92     mut hal_events: HalEventRegistry,
93     mut out_cmd_rx: UnboundedReceiver<NciPacket>,
94     mut out_data_rx: UnboundedReceiver<DataPacket>,
95     mut writer: W,
96 ) -> Result<()>
97 where
98     W: AsyncWriteExt + Unpin,
99 {
100     loop {
101         select! {
102             Some(cmd) = out_cmd_rx.recv() => write_nci(&mut writer, cmd).await?,
103             Some(data) = out_data_rx.recv() => write_nci(&mut writer, data).await?,
104             else => break,
105         }
106     }
107 
108     writer.shutdown().await?;
109     if let Some(evt) = hal_events.unregister(HalEvent::CloseComplete).await {
110         evt.send(HalEventStatus::Success).unwrap();
111     }
112     debug!("Dispatch outgoing finished.");
113     Ok(())
114 }
115 
write_nci<W, P>(writer: &mut W, cmd: P) -> Result<()> where W: AsyncWriteExt + Unpin, P: Packet,116 async fn write_nci<W, P>(writer: &mut W, cmd: P) -> Result<()>
117 where
118     W: AsyncWriteExt + Unpin,
119     P: Packet,
120 {
121     let b = cmd.to_bytes();
122     let mut data = BytesMut::with_capacity(b.len() + 2);
123     data.put_u16(b.len().try_into().unwrap());
124     data.extend(b);
125     writer.write_all(&data[..]).await?;
126     debug!("Sent {:?}", data);
127     Ok(())
128 }
129