xref: /aosp_15_r20/system/nfc/tools/casimir/src/main.rs (revision 7eba2f3b06c51ae21384f6a4f14577b668a869b3)
1*7eba2f3bSAndroid Build Coastguard Worker // Copyright 2023, The Android Open Source Project
2*7eba2f3bSAndroid Build Coastguard Worker //
3*7eba2f3bSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*7eba2f3bSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*7eba2f3bSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*7eba2f3bSAndroid Build Coastguard Worker //
7*7eba2f3bSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*7eba2f3bSAndroid Build Coastguard Worker //
9*7eba2f3bSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*7eba2f3bSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*7eba2f3bSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7eba2f3bSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*7eba2f3bSAndroid Build Coastguard Worker // limitations under the License.
14*7eba2f3bSAndroid Build Coastguard Worker 
15*7eba2f3bSAndroid Build Coastguard Worker //! NFCC and RF emulator.
16*7eba2f3bSAndroid Build Coastguard Worker 
17*7eba2f3bSAndroid Build Coastguard Worker use anyhow::Result;
18*7eba2f3bSAndroid Build Coastguard Worker use argh::FromArgs;
19*7eba2f3bSAndroid Build Coastguard Worker use log::{error, info, warn};
20*7eba2f3bSAndroid Build Coastguard Worker use rustutils::inherited_fd;
21*7eba2f3bSAndroid Build Coastguard Worker use std::future::Future;
22*7eba2f3bSAndroid Build Coastguard Worker use std::net::{Ipv4Addr, SocketAddrV4};
23*7eba2f3bSAndroid Build Coastguard Worker use std::pin::{pin, Pin};
24*7eba2f3bSAndroid Build Coastguard Worker use std::task::Context;
25*7eba2f3bSAndroid Build Coastguard Worker use std::task::Poll;
26*7eba2f3bSAndroid Build Coastguard Worker use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
27*7eba2f3bSAndroid Build Coastguard Worker use tokio::net::{TcpListener, UnixListener};
28*7eba2f3bSAndroid Build Coastguard Worker use tokio::select;
29*7eba2f3bSAndroid Build Coastguard Worker use tokio::sync::mpsc;
30*7eba2f3bSAndroid Build Coastguard Worker 
31*7eba2f3bSAndroid Build Coastguard Worker pub mod controller;
32*7eba2f3bSAndroid Build Coastguard Worker pub mod packets;
33*7eba2f3bSAndroid Build Coastguard Worker 
34*7eba2f3bSAndroid Build Coastguard Worker use controller::Controller;
35*7eba2f3bSAndroid Build Coastguard Worker use packets::{nci, rf};
36*7eba2f3bSAndroid Build Coastguard Worker 
37*7eba2f3bSAndroid Build Coastguard Worker const MAX_DEVICES: usize = 128;
38*7eba2f3bSAndroid Build Coastguard Worker type Id = u16;
39*7eba2f3bSAndroid Build Coastguard Worker 
40*7eba2f3bSAndroid Build Coastguard Worker /// Read RF Control and Data packets received on the RF transport.
41*7eba2f3bSAndroid Build Coastguard Worker /// Performs recombination of the segmented packets.
42*7eba2f3bSAndroid Build Coastguard Worker pub struct RfReader {
43*7eba2f3bSAndroid Build Coastguard Worker     socket: Pin<Box<dyn AsyncRead>>,
44*7eba2f3bSAndroid Build Coastguard Worker }
45*7eba2f3bSAndroid Build Coastguard Worker 
46*7eba2f3bSAndroid Build Coastguard Worker /// Write RF Control and Data packets received to the RF transport.
47*7eba2f3bSAndroid Build Coastguard Worker /// Performs segmentation of the packets.
48*7eba2f3bSAndroid Build Coastguard Worker pub struct RfWriter {
49*7eba2f3bSAndroid Build Coastguard Worker     socket: Pin<Box<dyn AsyncWrite>>,
50*7eba2f3bSAndroid Build Coastguard Worker }
51*7eba2f3bSAndroid Build Coastguard Worker 
52*7eba2f3bSAndroid Build Coastguard Worker impl RfReader {
53*7eba2f3bSAndroid Build Coastguard Worker     /// Create a new RF reader from an `AsyncRead` implementation.
new(socket: impl AsyncRead + 'static) -> Self54*7eba2f3bSAndroid Build Coastguard Worker     pub fn new(socket: impl AsyncRead + 'static) -> Self {
55*7eba2f3bSAndroid Build Coastguard Worker         RfReader { socket: Box::pin(socket) }
56*7eba2f3bSAndroid Build Coastguard Worker     }
57*7eba2f3bSAndroid Build Coastguard Worker 
58*7eba2f3bSAndroid Build Coastguard Worker     /// Read a single RF packet from the reader.
59*7eba2f3bSAndroid Build Coastguard Worker     /// RF packets are framed with the byte size encoded as little-endian u16.
read(&mut self) -> Result<Vec<u8>>60*7eba2f3bSAndroid Build Coastguard Worker     pub async fn read(&mut self) -> Result<Vec<u8>> {
61*7eba2f3bSAndroid Build Coastguard Worker         const HEADER_SIZE: usize = 2;
62*7eba2f3bSAndroid Build Coastguard Worker         let mut header_bytes = [0; HEADER_SIZE];
63*7eba2f3bSAndroid Build Coastguard Worker 
64*7eba2f3bSAndroid Build Coastguard Worker         // Read the header bytes.
65*7eba2f3bSAndroid Build Coastguard Worker         self.socket.read_exact(&mut header_bytes[0..HEADER_SIZE]).await?;
66*7eba2f3bSAndroid Build Coastguard Worker         let packet_length = u16::from_le_bytes(header_bytes) as usize;
67*7eba2f3bSAndroid Build Coastguard Worker 
68*7eba2f3bSAndroid Build Coastguard Worker         // Read the packet data.
69*7eba2f3bSAndroid Build Coastguard Worker         let mut packet_bytes = vec![0; packet_length];
70*7eba2f3bSAndroid Build Coastguard Worker         self.socket.read_exact(&mut packet_bytes).await?;
71*7eba2f3bSAndroid Build Coastguard Worker 
72*7eba2f3bSAndroid Build Coastguard Worker         Ok(packet_bytes)
73*7eba2f3bSAndroid Build Coastguard Worker     }
74*7eba2f3bSAndroid Build Coastguard Worker }
75*7eba2f3bSAndroid Build Coastguard Worker 
76*7eba2f3bSAndroid Build Coastguard Worker impl RfWriter {
77*7eba2f3bSAndroid Build Coastguard Worker     /// Create a new RF writer from an `AsyncWrite` implementation.
new(socket: impl AsyncWrite + 'static) -> Self78*7eba2f3bSAndroid Build Coastguard Worker     pub fn new(socket: impl AsyncWrite + 'static) -> Self {
79*7eba2f3bSAndroid Build Coastguard Worker         RfWriter { socket: Box::pin(socket) }
80*7eba2f3bSAndroid Build Coastguard Worker     }
81*7eba2f3bSAndroid Build Coastguard Worker 
82*7eba2f3bSAndroid Build Coastguard Worker     /// Write a single RF packet to the writer.
83*7eba2f3bSAndroid Build Coastguard Worker     /// RF packets are framed with the byte size encoded as little-endian u16.
write(&mut self, packet: &[u8]) -> Result<()>84*7eba2f3bSAndroid Build Coastguard Worker     async fn write(&mut self, packet: &[u8]) -> Result<()> {
85*7eba2f3bSAndroid Build Coastguard Worker         let packet_length: u16 = packet.len().try_into()?;
86*7eba2f3bSAndroid Build Coastguard Worker         let header_bytes = packet_length.to_le_bytes();
87*7eba2f3bSAndroid Build Coastguard Worker 
88*7eba2f3bSAndroid Build Coastguard Worker         // Write the header bytes.
89*7eba2f3bSAndroid Build Coastguard Worker         self.socket.write_all(&header_bytes).await?;
90*7eba2f3bSAndroid Build Coastguard Worker 
91*7eba2f3bSAndroid Build Coastguard Worker         // Write the packet data.
92*7eba2f3bSAndroid Build Coastguard Worker         self.socket.write_all(packet).await?;
93*7eba2f3bSAndroid Build Coastguard Worker 
94*7eba2f3bSAndroid Build Coastguard Worker         Ok(())
95*7eba2f3bSAndroid Build Coastguard Worker     }
96*7eba2f3bSAndroid Build Coastguard Worker }
97*7eba2f3bSAndroid Build Coastguard Worker 
98*7eba2f3bSAndroid Build Coastguard Worker /// Represent a generic NFC device interacting on the RF transport.
99*7eba2f3bSAndroid Build Coastguard Worker /// Devices communicate together through the RF mpsc channel.
100*7eba2f3bSAndroid Build Coastguard Worker /// NFCCs are an instance of Device.
101*7eba2f3bSAndroid Build Coastguard Worker pub struct Device {
102*7eba2f3bSAndroid Build Coastguard Worker     // Unique identifier associated with the device.
103*7eba2f3bSAndroid Build Coastguard Worker     // The identifier is assured never to be reused in the lifetime of
104*7eba2f3bSAndroid Build Coastguard Worker     // the emulator.
105*7eba2f3bSAndroid Build Coastguard Worker     id: u16,
106*7eba2f3bSAndroid Build Coastguard Worker     // Async task running the controller main loop.
107*7eba2f3bSAndroid Build Coastguard Worker     task: Pin<Box<dyn Future<Output = Result<()>>>>,
108*7eba2f3bSAndroid Build Coastguard Worker     // Channel for injecting RF data packets into the controller instance.
109*7eba2f3bSAndroid Build Coastguard Worker     rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
110*7eba2f3bSAndroid Build Coastguard Worker }
111*7eba2f3bSAndroid Build Coastguard Worker 
112*7eba2f3bSAndroid Build Coastguard Worker impl Device {
nci( id: Id, nci_rx: impl AsyncRead + 'static, nci_tx: impl AsyncWrite + 'static, controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Device113*7eba2f3bSAndroid Build Coastguard Worker     fn nci(
114*7eba2f3bSAndroid Build Coastguard Worker         id: Id,
115*7eba2f3bSAndroid Build Coastguard Worker         nci_rx: impl AsyncRead + 'static,
116*7eba2f3bSAndroid Build Coastguard Worker         nci_tx: impl AsyncWrite + 'static,
117*7eba2f3bSAndroid Build Coastguard Worker         controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
118*7eba2f3bSAndroid Build Coastguard Worker     ) -> Device {
119*7eba2f3bSAndroid Build Coastguard Worker         let (rf_tx, rf_rx) = mpsc::unbounded_channel();
120*7eba2f3bSAndroid Build Coastguard Worker         Device {
121*7eba2f3bSAndroid Build Coastguard Worker             id,
122*7eba2f3bSAndroid Build Coastguard Worker             rf_tx,
123*7eba2f3bSAndroid Build Coastguard Worker             task: Box::pin(async move {
124*7eba2f3bSAndroid Build Coastguard Worker                 Controller::run(
125*7eba2f3bSAndroid Build Coastguard Worker                     id,
126*7eba2f3bSAndroid Build Coastguard Worker                     pin!(nci::Reader::new(nci_rx).into_stream()),
127*7eba2f3bSAndroid Build Coastguard Worker                     nci::Writer::new(nci_tx),
128*7eba2f3bSAndroid Build Coastguard Worker                     rf_rx,
129*7eba2f3bSAndroid Build Coastguard Worker                     controller_rf_tx,
130*7eba2f3bSAndroid Build Coastguard Worker                 )
131*7eba2f3bSAndroid Build Coastguard Worker                 .await
132*7eba2f3bSAndroid Build Coastguard Worker             }),
133*7eba2f3bSAndroid Build Coastguard Worker         }
134*7eba2f3bSAndroid Build Coastguard Worker     }
135*7eba2f3bSAndroid Build Coastguard Worker 
rf( id: Id, socket_rx: impl AsyncRead + 'static, socket_tx: impl AsyncWrite + 'static, controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Device136*7eba2f3bSAndroid Build Coastguard Worker     fn rf(
137*7eba2f3bSAndroid Build Coastguard Worker         id: Id,
138*7eba2f3bSAndroid Build Coastguard Worker         socket_rx: impl AsyncRead + 'static,
139*7eba2f3bSAndroid Build Coastguard Worker         socket_tx: impl AsyncWrite + 'static,
140*7eba2f3bSAndroid Build Coastguard Worker         controller_rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
141*7eba2f3bSAndroid Build Coastguard Worker     ) -> Device {
142*7eba2f3bSAndroid Build Coastguard Worker         let (rf_tx, mut rf_rx) = mpsc::unbounded_channel();
143*7eba2f3bSAndroid Build Coastguard Worker         Device {
144*7eba2f3bSAndroid Build Coastguard Worker             id,
145*7eba2f3bSAndroid Build Coastguard Worker             rf_tx,
146*7eba2f3bSAndroid Build Coastguard Worker             task: Box::pin(async move {
147*7eba2f3bSAndroid Build Coastguard Worker                 let mut rf_reader = RfReader::new(socket_rx);
148*7eba2f3bSAndroid Build Coastguard Worker                 let mut rf_writer = RfWriter::new(socket_tx);
149*7eba2f3bSAndroid Build Coastguard Worker 
150*7eba2f3bSAndroid Build Coastguard Worker                 let result: Result<((), ())> = futures::future::try_join(
151*7eba2f3bSAndroid Build Coastguard Worker                     async {
152*7eba2f3bSAndroid Build Coastguard Worker                         loop {
153*7eba2f3bSAndroid Build Coastguard Worker                             // Replace the sender identifier in the packet
154*7eba2f3bSAndroid Build Coastguard Worker                             // with the assigned number for the RF connection.
155*7eba2f3bSAndroid Build Coastguard Worker                             // TODO: currently the generated API does not allow
156*7eba2f3bSAndroid Build Coastguard Worker                             // modifying the parsed fields so the change needs to be
157*7eba2f3bSAndroid Build Coastguard Worker                             // applied to the unparsed packet.
158*7eba2f3bSAndroid Build Coastguard Worker                             let mut packet_bytes = rf_reader.read().await?;
159*7eba2f3bSAndroid Build Coastguard Worker                             packet_bytes[0..2].copy_from_slice(&id.to_le_bytes());
160*7eba2f3bSAndroid Build Coastguard Worker 
161*7eba2f3bSAndroid Build Coastguard Worker                             // Parse the input packet.
162*7eba2f3bSAndroid Build Coastguard Worker                             let packet = rf::RfPacket::parse(&packet_bytes)?;
163*7eba2f3bSAndroid Build Coastguard Worker 
164*7eba2f3bSAndroid Build Coastguard Worker                             // Forward the packet to other devices.
165*7eba2f3bSAndroid Build Coastguard Worker                             controller_rf_tx.send(packet)?;
166*7eba2f3bSAndroid Build Coastguard Worker                         }
167*7eba2f3bSAndroid Build Coastguard Worker                     },
168*7eba2f3bSAndroid Build Coastguard Worker                     async {
169*7eba2f3bSAndroid Build Coastguard Worker                         loop {
170*7eba2f3bSAndroid Build Coastguard Worker                             // Forward the packet to the socket connection.
171*7eba2f3bSAndroid Build Coastguard Worker                             use pdl_runtime::Packet;
172*7eba2f3bSAndroid Build Coastguard Worker                             let packet = rf_rx
173*7eba2f3bSAndroid Build Coastguard Worker                                 .recv()
174*7eba2f3bSAndroid Build Coastguard Worker                                 .await
175*7eba2f3bSAndroid Build Coastguard Worker                                 .ok_or(anyhow::anyhow!("rf_rx channel closed"))?;
176*7eba2f3bSAndroid Build Coastguard Worker                             rf_writer.write(&packet.encode_to_vec()?).await?;
177*7eba2f3bSAndroid Build Coastguard Worker                         }
178*7eba2f3bSAndroid Build Coastguard Worker                     },
179*7eba2f3bSAndroid Build Coastguard Worker                 )
180*7eba2f3bSAndroid Build Coastguard Worker                 .await;
181*7eba2f3bSAndroid Build Coastguard Worker 
182*7eba2f3bSAndroid Build Coastguard Worker                 result?;
183*7eba2f3bSAndroid Build Coastguard Worker                 Ok(())
184*7eba2f3bSAndroid Build Coastguard Worker             }),
185*7eba2f3bSAndroid Build Coastguard Worker         }
186*7eba2f3bSAndroid Build Coastguard Worker     }
187*7eba2f3bSAndroid Build Coastguard Worker }
188*7eba2f3bSAndroid Build Coastguard Worker 
189*7eba2f3bSAndroid Build Coastguard Worker struct Scene {
190*7eba2f3bSAndroid Build Coastguard Worker     next_id: u16,
191*7eba2f3bSAndroid Build Coastguard Worker     waker: Option<std::task::Waker>,
192*7eba2f3bSAndroid Build Coastguard Worker     devices: [Option<Device>; MAX_DEVICES],
193*7eba2f3bSAndroid Build Coastguard Worker }
194*7eba2f3bSAndroid Build Coastguard Worker 
195*7eba2f3bSAndroid Build Coastguard Worker impl Default for Scene {
default() -> Self196*7eba2f3bSAndroid Build Coastguard Worker     fn default() -> Self {
197*7eba2f3bSAndroid Build Coastguard Worker         const NONE: Option<Device> = None;
198*7eba2f3bSAndroid Build Coastguard Worker         Scene { next_id: 0, waker: None, devices: [NONE; MAX_DEVICES] }
199*7eba2f3bSAndroid Build Coastguard Worker     }
200*7eba2f3bSAndroid Build Coastguard Worker }
201*7eba2f3bSAndroid Build Coastguard Worker 
202*7eba2f3bSAndroid Build Coastguard Worker impl Scene {
new() -> Scene203*7eba2f3bSAndroid Build Coastguard Worker     fn new() -> Scene {
204*7eba2f3bSAndroid Build Coastguard Worker         Default::default()
205*7eba2f3bSAndroid Build Coastguard Worker     }
206*7eba2f3bSAndroid Build Coastguard Worker 
wake(&mut self)207*7eba2f3bSAndroid Build Coastguard Worker     fn wake(&mut self) {
208*7eba2f3bSAndroid Build Coastguard Worker         if let Some(waker) = self.waker.take() {
209*7eba2f3bSAndroid Build Coastguard Worker             waker.wake()
210*7eba2f3bSAndroid Build Coastguard Worker         }
211*7eba2f3bSAndroid Build Coastguard Worker     }
212*7eba2f3bSAndroid Build Coastguard Worker 
add_device(&mut self, builder: impl FnOnce(Id) -> Device) -> Result<Id>213*7eba2f3bSAndroid Build Coastguard Worker     fn add_device(&mut self, builder: impl FnOnce(Id) -> Device) -> Result<Id> {
214*7eba2f3bSAndroid Build Coastguard Worker         for n in 0..MAX_DEVICES {
215*7eba2f3bSAndroid Build Coastguard Worker             if self.devices[n].is_none() {
216*7eba2f3bSAndroid Build Coastguard Worker                 self.devices[n] = Some(builder(self.next_id));
217*7eba2f3bSAndroid Build Coastguard Worker                 self.next_id += 1;
218*7eba2f3bSAndroid Build Coastguard Worker                 self.wake();
219*7eba2f3bSAndroid Build Coastguard Worker                 return Ok(n as Id);
220*7eba2f3bSAndroid Build Coastguard Worker             }
221*7eba2f3bSAndroid Build Coastguard Worker         }
222*7eba2f3bSAndroid Build Coastguard Worker         Err(anyhow::anyhow!("max number of connections reached"))
223*7eba2f3bSAndroid Build Coastguard Worker     }
224*7eba2f3bSAndroid Build Coastguard Worker 
disconnect(&mut self, n: usize)225*7eba2f3bSAndroid Build Coastguard Worker     fn disconnect(&mut self, n: usize) {
226*7eba2f3bSAndroid Build Coastguard Worker         let id = self.devices[n].as_ref().unwrap().id;
227*7eba2f3bSAndroid Build Coastguard Worker         self.devices[n] = None;
228*7eba2f3bSAndroid Build Coastguard Worker         for other_n in 0..MAX_DEVICES {
229*7eba2f3bSAndroid Build Coastguard Worker             let Some(ref device) = self.devices[other_n] else { continue };
230*7eba2f3bSAndroid Build Coastguard Worker             assert!(n != other_n);
231*7eba2f3bSAndroid Build Coastguard Worker             device
232*7eba2f3bSAndroid Build Coastguard Worker                 .rf_tx
233*7eba2f3bSAndroid Build Coastguard Worker                 .send(
234*7eba2f3bSAndroid Build Coastguard Worker                     rf::DeactivateNotificationBuilder {
235*7eba2f3bSAndroid Build Coastguard Worker                         type_: rf::DeactivateType::Discovery,
236*7eba2f3bSAndroid Build Coastguard Worker                         reason: rf::DeactivateReason::RfLinkLoss,
237*7eba2f3bSAndroid Build Coastguard Worker                         sender: id,
238*7eba2f3bSAndroid Build Coastguard Worker                         receiver: device.id,
239*7eba2f3bSAndroid Build Coastguard Worker                         power_level: 255,
240*7eba2f3bSAndroid Build Coastguard Worker                         technology: rf::Technology::NfcA,
241*7eba2f3bSAndroid Build Coastguard Worker                         protocol: rf::Protocol::Undetermined,
242*7eba2f3bSAndroid Build Coastguard Worker                     }
243*7eba2f3bSAndroid Build Coastguard Worker                     .into(),
244*7eba2f3bSAndroid Build Coastguard Worker                 )
245*7eba2f3bSAndroid Build Coastguard Worker                 .expect("failed to send deactive notification")
246*7eba2f3bSAndroid Build Coastguard Worker         }
247*7eba2f3bSAndroid Build Coastguard Worker     }
248*7eba2f3bSAndroid Build Coastguard Worker 
send(&self, packet: &rf::RfPacket) -> Result<()>249*7eba2f3bSAndroid Build Coastguard Worker     fn send(&self, packet: &rf::RfPacket) -> Result<()> {
250*7eba2f3bSAndroid Build Coastguard Worker         for n in 0..MAX_DEVICES {
251*7eba2f3bSAndroid Build Coastguard Worker             let Some(ref device) = self.devices[n] else { continue };
252*7eba2f3bSAndroid Build Coastguard Worker             if packet.get_sender() != device.id
253*7eba2f3bSAndroid Build Coastguard Worker                 && (packet.get_receiver() == u16::MAX || packet.get_receiver() == device.id)
254*7eba2f3bSAndroid Build Coastguard Worker             {
255*7eba2f3bSAndroid Build Coastguard Worker                 device.rf_tx.send(packet.to_owned())?;
256*7eba2f3bSAndroid Build Coastguard Worker             }
257*7eba2f3bSAndroid Build Coastguard Worker         }
258*7eba2f3bSAndroid Build Coastguard Worker 
259*7eba2f3bSAndroid Build Coastguard Worker         Ok(())
260*7eba2f3bSAndroid Build Coastguard Worker     }
261*7eba2f3bSAndroid Build Coastguard Worker }
262*7eba2f3bSAndroid Build Coastguard Worker 
263*7eba2f3bSAndroid Build Coastguard Worker impl Future for Scene {
264*7eba2f3bSAndroid Build Coastguard Worker     type Output = ();
265*7eba2f3bSAndroid Build Coastguard Worker 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()>266*7eba2f3bSAndroid Build Coastguard Worker     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
267*7eba2f3bSAndroid Build Coastguard Worker         for n in 0..MAX_DEVICES {
268*7eba2f3bSAndroid Build Coastguard Worker             let dropped = match self.devices[n] {
269*7eba2f3bSAndroid Build Coastguard Worker                 Some(ref mut device) => match device.task.as_mut().poll(cx) {
270*7eba2f3bSAndroid Build Coastguard Worker                     Poll::Ready(Ok(_)) => unreachable!(),
271*7eba2f3bSAndroid Build Coastguard Worker                     Poll::Ready(Err(err)) => {
272*7eba2f3bSAndroid Build Coastguard Worker                         warn!("dropping device {}: {}", n, err);
273*7eba2f3bSAndroid Build Coastguard Worker                         true
274*7eba2f3bSAndroid Build Coastguard Worker                     }
275*7eba2f3bSAndroid Build Coastguard Worker                     Poll::Pending => false,
276*7eba2f3bSAndroid Build Coastguard Worker                 },
277*7eba2f3bSAndroid Build Coastguard Worker                 None => false,
278*7eba2f3bSAndroid Build Coastguard Worker             };
279*7eba2f3bSAndroid Build Coastguard Worker             if dropped {
280*7eba2f3bSAndroid Build Coastguard Worker                 self.disconnect(n)
281*7eba2f3bSAndroid Build Coastguard Worker             }
282*7eba2f3bSAndroid Build Coastguard Worker         }
283*7eba2f3bSAndroid Build Coastguard Worker         self.waker = Some(cx.waker().clone());
284*7eba2f3bSAndroid Build Coastguard Worker         Poll::Pending
285*7eba2f3bSAndroid Build Coastguard Worker     }
286*7eba2f3bSAndroid Build Coastguard Worker }
287*7eba2f3bSAndroid Build Coastguard Worker 
288*7eba2f3bSAndroid Build Coastguard Worker #[derive(FromArgs, Debug)]
289*7eba2f3bSAndroid Build Coastguard Worker /// Nfc emulator.
290*7eba2f3bSAndroid Build Coastguard Worker struct Opt {
291*7eba2f3bSAndroid Build Coastguard Worker     #[argh(option)]
292*7eba2f3bSAndroid Build Coastguard Worker     /// configure the TCP port for the NCI server.
293*7eba2f3bSAndroid Build Coastguard Worker     nci_port: Option<u16>,
294*7eba2f3bSAndroid Build Coastguard Worker     #[argh(option)]
295*7eba2f3bSAndroid Build Coastguard Worker     /// configure a preexisting unix server fd for the NCI server.
296*7eba2f3bSAndroid Build Coastguard Worker     nci_unix_fd: Option<i32>,
297*7eba2f3bSAndroid Build Coastguard Worker     #[argh(option)]
298*7eba2f3bSAndroid Build Coastguard Worker     /// configure the TCP port for the RF server.
299*7eba2f3bSAndroid Build Coastguard Worker     rf_port: Option<u16>,
300*7eba2f3bSAndroid Build Coastguard Worker     #[argh(option)]
301*7eba2f3bSAndroid Build Coastguard Worker     /// configure a preexisting unix server fd for the RF server.
302*7eba2f3bSAndroid Build Coastguard Worker     rf_unix_fd: Option<i32>,
303*7eba2f3bSAndroid Build Coastguard Worker }
304*7eba2f3bSAndroid Build Coastguard Worker 
305*7eba2f3bSAndroid Build Coastguard Worker /// Abstraction between different server sources
306*7eba2f3bSAndroid Build Coastguard Worker enum Listener {
307*7eba2f3bSAndroid Build Coastguard Worker     Tcp(TcpListener),
308*7eba2f3bSAndroid Build Coastguard Worker     #[allow(unused)]
309*7eba2f3bSAndroid Build Coastguard Worker     Unix(UnixListener),
310*7eba2f3bSAndroid Build Coastguard Worker }
311*7eba2f3bSAndroid Build Coastguard Worker 
312*7eba2f3bSAndroid Build Coastguard Worker impl Listener {
accept_split( &self, ) -> Result<(Pin<Box<dyn AsyncRead>>, Pin<Box<dyn AsyncWrite>>, String)>313*7eba2f3bSAndroid Build Coastguard Worker     async fn accept_split(
314*7eba2f3bSAndroid Build Coastguard Worker         &self,
315*7eba2f3bSAndroid Build Coastguard Worker     ) -> Result<(Pin<Box<dyn AsyncRead>>, Pin<Box<dyn AsyncWrite>>, String)> {
316*7eba2f3bSAndroid Build Coastguard Worker         match self {
317*7eba2f3bSAndroid Build Coastguard Worker             Listener::Tcp(tcp) => {
318*7eba2f3bSAndroid Build Coastguard Worker                 let (socket, addr) = tcp.accept().await?;
319*7eba2f3bSAndroid Build Coastguard Worker                 let (rx, tx) = socket.into_split();
320*7eba2f3bSAndroid Build Coastguard Worker                 Ok((Box::pin(rx), Box::pin(tx), format!("{}", addr)))
321*7eba2f3bSAndroid Build Coastguard Worker             }
322*7eba2f3bSAndroid Build Coastguard Worker             Listener::Unix(unix) => {
323*7eba2f3bSAndroid Build Coastguard Worker                 let (socket, addr) = unix.accept().await?;
324*7eba2f3bSAndroid Build Coastguard Worker                 let (rx, tx) = socket.into_split();
325*7eba2f3bSAndroid Build Coastguard Worker                 Ok((Box::pin(rx), Box::pin(tx), format!("{:?}", addr)))
326*7eba2f3bSAndroid Build Coastguard Worker             }
327*7eba2f3bSAndroid Build Coastguard Worker         }
328*7eba2f3bSAndroid Build Coastguard Worker     }
329*7eba2f3bSAndroid Build Coastguard Worker }
330*7eba2f3bSAndroid Build Coastguard Worker 
331*7eba2f3bSAndroid Build Coastguard Worker #[tokio::main]
run() -> Result<()>332*7eba2f3bSAndroid Build Coastguard Worker async fn run() -> Result<()> {
333*7eba2f3bSAndroid Build Coastguard Worker     env_logger::init_from_env(
334*7eba2f3bSAndroid Build Coastguard Worker         env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "debug"),
335*7eba2f3bSAndroid Build Coastguard Worker     );
336*7eba2f3bSAndroid Build Coastguard Worker 
337*7eba2f3bSAndroid Build Coastguard Worker     let opt: Opt = argh::from_env();
338*7eba2f3bSAndroid Build Coastguard Worker 
339*7eba2f3bSAndroid Build Coastguard Worker     let nci_listener = match (opt.nci_port, opt.nci_unix_fd) {
340*7eba2f3bSAndroid Build Coastguard Worker         (None, Some(unix_fd)) => {
341*7eba2f3bSAndroid Build Coastguard Worker             let owned_fd = inherited_fd::take_fd_ownership(unix_fd)?;
342*7eba2f3bSAndroid Build Coastguard Worker             let nci_listener = std::os::unix::net::UnixListener::from(owned_fd);
343*7eba2f3bSAndroid Build Coastguard Worker             nci_listener.set_nonblocking(true)?;
344*7eba2f3bSAndroid Build Coastguard Worker             let nci_listener = UnixListener::from_std(nci_listener)?;
345*7eba2f3bSAndroid Build Coastguard Worker             info!("Listening for NCI connections on fd {}", unix_fd);
346*7eba2f3bSAndroid Build Coastguard Worker             Listener::Unix(nci_listener)
347*7eba2f3bSAndroid Build Coastguard Worker         }
348*7eba2f3bSAndroid Build Coastguard Worker         (port, None) => {
349*7eba2f3bSAndroid Build Coastguard Worker             let port = port.unwrap_or(7000);
350*7eba2f3bSAndroid Build Coastguard Worker             let nci_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
351*7eba2f3bSAndroid Build Coastguard Worker             let nci_listener = TcpListener::bind(nci_addr).await?;
352*7eba2f3bSAndroid Build Coastguard Worker             info!("Listening for NCI connections at address {}", nci_addr);
353*7eba2f3bSAndroid Build Coastguard Worker             Listener::Tcp(nci_listener)
354*7eba2f3bSAndroid Build Coastguard Worker         }
355*7eba2f3bSAndroid Build Coastguard Worker         _ => anyhow::bail!("Specify at most one of `--nci-port` and `--nci-unix-fd`."),
356*7eba2f3bSAndroid Build Coastguard Worker     };
357*7eba2f3bSAndroid Build Coastguard Worker 
358*7eba2f3bSAndroid Build Coastguard Worker     let rf_listener = match (opt.rf_port, opt.rf_unix_fd) {
359*7eba2f3bSAndroid Build Coastguard Worker         (None, Some(unix_fd)) => {
360*7eba2f3bSAndroid Build Coastguard Worker             let owned_fd = inherited_fd::take_fd_ownership(unix_fd)?;
361*7eba2f3bSAndroid Build Coastguard Worker             let nci_listener = std::os::unix::net::UnixListener::from(owned_fd);
362*7eba2f3bSAndroid Build Coastguard Worker             nci_listener.set_nonblocking(true)?;
363*7eba2f3bSAndroid Build Coastguard Worker             let nci_listener = UnixListener::from_std(nci_listener)?;
364*7eba2f3bSAndroid Build Coastguard Worker             info!("Listening for RF connections on fd {}", unix_fd);
365*7eba2f3bSAndroid Build Coastguard Worker             Listener::Unix(nci_listener)
366*7eba2f3bSAndroid Build Coastguard Worker         }
367*7eba2f3bSAndroid Build Coastguard Worker         (port, None) => {
368*7eba2f3bSAndroid Build Coastguard Worker             let port = port.unwrap_or(7001);
369*7eba2f3bSAndroid Build Coastguard Worker             let rf_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
370*7eba2f3bSAndroid Build Coastguard Worker             let rf_listener = TcpListener::bind(rf_addr).await?;
371*7eba2f3bSAndroid Build Coastguard Worker             info!("Listening for RF connections at address {}", rf_addr);
372*7eba2f3bSAndroid Build Coastguard Worker             Listener::Tcp(rf_listener)
373*7eba2f3bSAndroid Build Coastguard Worker         }
374*7eba2f3bSAndroid Build Coastguard Worker         _ => anyhow::bail!("Specify at most one of `--rf-port` and `--rf-unix-fd`"),
375*7eba2f3bSAndroid Build Coastguard Worker     };
376*7eba2f3bSAndroid Build Coastguard Worker 
377*7eba2f3bSAndroid Build Coastguard Worker     let (rf_tx, mut rf_rx) = mpsc::unbounded_channel();
378*7eba2f3bSAndroid Build Coastguard Worker     let mut scene = Scene::new();
379*7eba2f3bSAndroid Build Coastguard Worker     loop {
380*7eba2f3bSAndroid Build Coastguard Worker         select! {
381*7eba2f3bSAndroid Build Coastguard Worker             result = nci_listener.accept_split() => {
382*7eba2f3bSAndroid Build Coastguard Worker                 let (socket_rx, socket_tx, addr) = result?;
383*7eba2f3bSAndroid Build Coastguard Worker                 info!("Incoming NCI connection from {}", addr);
384*7eba2f3bSAndroid Build Coastguard Worker                 match scene.add_device(|id| Device::nci(id, socket_rx, socket_tx, rf_tx.clone())) {
385*7eba2f3bSAndroid Build Coastguard Worker                     Ok(id) => info!("Accepted NCI connection from {} in slot {}", addr, id),
386*7eba2f3bSAndroid Build Coastguard Worker                     Err(err) => error!("Failed to accept NCI connection from {}: {}", addr, err)
387*7eba2f3bSAndroid Build Coastguard Worker                 }
388*7eba2f3bSAndroid Build Coastguard Worker             },
389*7eba2f3bSAndroid Build Coastguard Worker             result = rf_listener.accept_split() => {
390*7eba2f3bSAndroid Build Coastguard Worker                 let (socket_rx, socket_tx, addr) = result?;
391*7eba2f3bSAndroid Build Coastguard Worker                 info!("Incoming RF connection from {}", addr);
392*7eba2f3bSAndroid Build Coastguard Worker                 match scene.add_device(|id| Device::rf(id, socket_rx, socket_tx, rf_tx.clone())) {
393*7eba2f3bSAndroid Build Coastguard Worker                     Ok(id) => info!("Accepted RF connection from {} in slot {}", addr, id),
394*7eba2f3bSAndroid Build Coastguard Worker                     Err(err) => error!("Failed to accept RF connection from {}: {}", addr, err)
395*7eba2f3bSAndroid Build Coastguard Worker                 }
396*7eba2f3bSAndroid Build Coastguard Worker             },
397*7eba2f3bSAndroid Build Coastguard Worker             _ = &mut scene => (),
398*7eba2f3bSAndroid Build Coastguard Worker             result = rf_rx.recv() => {
399*7eba2f3bSAndroid Build Coastguard Worker                 let packet = result.ok_or(anyhow::anyhow!("rf_rx channel closed"))?;
400*7eba2f3bSAndroid Build Coastguard Worker                 scene.send(&packet)?
401*7eba2f3bSAndroid Build Coastguard Worker             }
402*7eba2f3bSAndroid Build Coastguard Worker         }
403*7eba2f3bSAndroid Build Coastguard Worker     }
404*7eba2f3bSAndroid Build Coastguard Worker }
405*7eba2f3bSAndroid Build Coastguard Worker 
main() -> Result<()>406*7eba2f3bSAndroid Build Coastguard Worker fn main() -> Result<()> {
407*7eba2f3bSAndroid Build Coastguard Worker     // Safety: First function call in the `main` function, before any other library calls
408*7eba2f3bSAndroid Build Coastguard Worker     unsafe { inherited_fd::init_once()? };
409*7eba2f3bSAndroid Build Coastguard Worker     run()
410*7eba2f3bSAndroid Build Coastguard Worker }
411