1 // Copyright 2023, 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 //! Packet parsers and serializers.
16 
17 /// NCI packet parser and serializer.
18 pub mod nci {
19     #![allow(clippy::all)]
20     #![allow(unused)]
21     #![allow(missing_docs)]
22 
23     include!(concat!(env!("OUT_DIR"), "/nci_packets.rs"));
24 
25     impl ConnId {
26         /// Create a Conn ID with `id` as an offset in the range of dynamic
27         /// identifiers.
from_dynamic(id: u8) -> Self28         pub fn from_dynamic(id: u8) -> Self {
29             ConnId::try_from(id as u8 + 2).unwrap()
30         }
31 
32         /// Return the index for a dynamic Conn ID.
to_dynamic(id: Private<u8>) -> u833         pub fn to_dynamic(id: Private<u8>) -> u8 {
34             *id - 2
35         }
36     }
37 
38     impl RfDiscoveryId {
39         /// Create the default reserved RF Discovery ID.
reserved() -> Self40         pub fn reserved() -> Self {
41             RfDiscoveryId::try_from(0).unwrap()
42         }
43 
44         /// Create an RF Discovery ID with `id` as an offset in the range of
45         /// non-reserved identifiers.
from_index(id: usize) -> Self46         pub fn from_index(id: usize) -> Self {
47             RfDiscoveryId::try_from(id as u8 + 1).unwrap()
48         }
49 
50         /// Return the index for a valid RF Discovery ID.
to_index(id: Private<u8>) -> usize51         pub fn to_index(id: Private<u8>) -> usize {
52             *id as usize - 1
53         }
54     }
55 
56     impl NfceeId {
nfcee(id: u8) -> Self57         pub fn nfcee(id: u8) -> Self {
58             NfceeId::try_from(id).unwrap()
59         }
60 
hci_nfcee(id: u8) -> Self61         pub fn hci_nfcee(id: u8) -> Self {
62             NfceeId::try_from(id).unwrap()
63         }
64     }
65 
66     use futures::stream::{self, Stream};
67     use std::pin::Pin;
68     use tokio::io::{AsyncRead, AsyncWrite};
69     use tokio::sync::Mutex;
70 
71     /// Read NCI Control and Data packets received on the NCI transport.
72     /// Performs recombination of the segmented packets.
73     pub struct Reader {
74         socket: Pin<Box<dyn AsyncRead>>,
75     }
76 
77     /// Write NCI Control and Data packets received to the NCI transport.
78     /// Performs segmentation of the packets.
79     pub struct Writer {
80         socket: Pin<Box<dyn AsyncWrite>>,
81     }
82 
83     impl Reader {
84         /// Create an NCI reader from an NCI transport.
new<T: AsyncRead + 'static>(rx: T) -> Self85         pub fn new<T: AsyncRead + 'static>(rx: T) -> Self {
86             Reader { socket: Box::pin(rx) }
87         }
88 
89         /// Read a single NCI packet from the reader. The packet is automatically
90         /// re-assembled if segmented on the NCI transport.
read(&mut self) -> anyhow::Result<Vec<u8>>91         pub async fn read(&mut self) -> anyhow::Result<Vec<u8>> {
92             use tokio::io::AsyncReadExt;
93 
94             const HEADER_SIZE: usize = 3;
95             let mut complete_packet = vec![0; HEADER_SIZE];
96 
97             // Note on reassembly:
98             // - for each segment of a Control Message, the header of the
99             //   Control Packet SHALL contain the same MT, GID and OID values,
100             // - for each segment of a Data Message the header of the Data
101             //   Packet SHALL contain the same MT and Conn ID.
102             // Thus it is correct to keep only the last header of the segmented
103             // packet.
104             loop {
105                 // Read the common packet header.
106                 self.socket.read_exact(&mut complete_packet[0..HEADER_SIZE]).await?;
107                 let header = PacketHeader::parse(&complete_packet[0..HEADER_SIZE])?;
108 
109                 // Read the packet payload.
110                 let payload_length = header.get_payload_length() as usize;
111                 let mut payload_bytes = vec![0; payload_length];
112                 self.socket.read_exact(&mut payload_bytes).await?;
113                 complete_packet.extend(payload_bytes);
114 
115                 // Check the Packet Boundary Flag.
116                 match header.get_pbf() {
117                     PacketBoundaryFlag::CompleteOrFinal => return Ok(complete_packet),
118                     PacketBoundaryFlag::Incomplete => (),
119                 }
120             }
121         }
122 
into_stream(self) -> impl Stream<Item = anyhow::Result<Vec<u8>>>123         pub fn into_stream(self) -> impl Stream<Item = anyhow::Result<Vec<u8>>> {
124             stream::try_unfold(self, |mut reader| async move {
125                 Ok(Some((reader.read().await?, reader)))
126             })
127         }
128     }
129 
130     /// A mutable reference to the stream returned by into_stream
131     pub type StreamRefMut<'a> = Pin<&'a mut dyn Stream<Item = anyhow::Result<Vec<u8>>>>;
132 
133     impl Writer {
134         /// Create an NCI writer from an NCI transport.
new<T: AsyncWrite + 'static>(rx: T) -> Self135         pub fn new<T: AsyncWrite + 'static>(rx: T) -> Self {
136             Writer { socket: Box::pin(rx) }
137         }
138 
139         /// Write a single NCI packet to the writer. The packet is automatically
140         /// segmented if the payload exceeds the maximum size limit.
write(&mut self, mut packet: &[u8]) -> anyhow::Result<()>141         pub async fn write(&mut self, mut packet: &[u8]) -> anyhow::Result<()> {
142             use tokio::io::AsyncWriteExt;
143 
144             let mut header_bytes = [packet[0], packet[1], 0];
145             packet = &packet[3..];
146 
147             loop {
148                 // Update header with framing information.
149                 let chunk_length = std::cmp::min(255, packet.len());
150                 let pbf = if chunk_length < packet.len() {
151                     PacketBoundaryFlag::Incomplete
152                 } else {
153                     PacketBoundaryFlag::CompleteOrFinal
154                 };
155                 const PBF_MASK: u8 = 0x10;
156                 header_bytes[0] &= !PBF_MASK;
157                 header_bytes[0] |= (pbf as u8) << 4;
158                 header_bytes[2] = chunk_length as u8;
159 
160                 // Write the header and payload segment bytes.
161                 self.socket.write_all(&header_bytes).await?;
162                 self.socket.write_all(&packet[..chunk_length]).await?;
163                 packet = &packet[chunk_length..];
164 
165                 if packet.is_empty() {
166                     return Ok(());
167                 }
168             }
169         }
170     }
171 }
172 
173 /// RF packet parser and serializer.
174 pub mod rf {
175     #![allow(clippy::all)]
176     #![allow(unused)]
177     #![allow(missing_docs)]
178 
179     include!(concat!(env!("OUT_DIR"), "/rf_packets.rs"));
180 }
181 
182 impl From<rf::Protocol> for nci::RfProtocolType {
from(protocol: rf::Protocol) -> Self183     fn from(protocol: rf::Protocol) -> Self {
184         match protocol {
185             rf::Protocol::Undetermined => nci::RfProtocolType::Undetermined,
186             rf::Protocol::T1t => nci::RfProtocolType::T1t,
187             rf::Protocol::T2t => nci::RfProtocolType::T2t,
188             rf::Protocol::T3t => nci::RfProtocolType::T3t,
189             rf::Protocol::IsoDep => nci::RfProtocolType::IsoDep,
190             rf::Protocol::NfcDep => nci::RfProtocolType::NfcDep,
191             rf::Protocol::T5t => nci::RfProtocolType::T5t,
192             rf::Protocol::Ndef => nci::RfProtocolType::Ndef,
193         }
194     }
195 }
196 
197 impl From<nci::RfProtocolType> for rf::Protocol {
from(protocol: nci::RfProtocolType) -> Self198     fn from(protocol: nci::RfProtocolType) -> Self {
199         match protocol {
200             nci::RfProtocolType::Undetermined => rf::Protocol::Undetermined,
201             nci::RfProtocolType::T1t => rf::Protocol::T1t,
202             nci::RfProtocolType::T2t => rf::Protocol::T2t,
203             nci::RfProtocolType::T3t => rf::Protocol::T3t,
204             nci::RfProtocolType::IsoDep => rf::Protocol::IsoDep,
205             nci::RfProtocolType::NfcDep => rf::Protocol::NfcDep,
206             nci::RfProtocolType::T5t => rf::Protocol::T5t,
207             nci::RfProtocolType::Ndef => rf::Protocol::Ndef,
208         }
209     }
210 }
211 
212 impl TryFrom<nci::RfTechnologyAndMode> for rf::Technology {
213     type Error = nci::RfTechnologyAndMode;
try_from(protocol: nci::RfTechnologyAndMode) -> Result<Self, Self::Error>214     fn try_from(protocol: nci::RfTechnologyAndMode) -> Result<Self, Self::Error> {
215         Ok(match protocol {
216             nci::RfTechnologyAndMode::NfcAPassivePollMode
217             | nci::RfTechnologyAndMode::NfcAPassiveListenMode => rf::Technology::NfcA,
218             nci::RfTechnologyAndMode::NfcBPassivePollMode
219             | nci::RfTechnologyAndMode::NfcBPassiveListenMode => rf::Technology::NfcB,
220             nci::RfTechnologyAndMode::NfcFPassivePollMode
221             | nci::RfTechnologyAndMode::NfcFPassiveListenMode => rf::Technology::NfcF,
222             nci::RfTechnologyAndMode::NfcVPassivePollMode => rf::Technology::NfcV,
223             _ => return Err(protocol),
224         })
225     }
226 }
227 
228 impl From<rf::DeactivateType> for nci::DeactivationType {
from(type_: rf::DeactivateType) -> Self229     fn from(type_: rf::DeactivateType) -> Self {
230         match type_ {
231             rf::DeactivateType::IdleMode => nci::DeactivationType::IdleMode,
232             rf::DeactivateType::SleepMode => nci::DeactivationType::SleepMode,
233             rf::DeactivateType::SleepAfMode => nci::DeactivationType::SleepAfMode,
234             rf::DeactivateType::Discovery => nci::DeactivationType::Discovery,
235         }
236     }
237 }
238 
239 impl From<nci::DeactivationType> for rf::DeactivateType {
from(type_: nci::DeactivationType) -> Self240     fn from(type_: nci::DeactivationType) -> Self {
241         match type_ {
242             nci::DeactivationType::IdleMode => rf::DeactivateType::IdleMode,
243             nci::DeactivationType::SleepMode => rf::DeactivateType::SleepMode,
244             nci::DeactivationType::SleepAfMode => rf::DeactivateType::SleepAfMode,
245             nci::DeactivationType::Discovery => rf::DeactivateType::Discovery,
246         }
247     }
248 }
249 
250 impl From<rf::DeactivateReason> for nci::DeactivationReason {
from(reason: rf::DeactivateReason) -> Self251     fn from(reason: rf::DeactivateReason) -> Self {
252         match reason {
253             rf::DeactivateReason::DhRequest => nci::DeactivationReason::DhRequest,
254             rf::DeactivateReason::EndpointRequest => nci::DeactivationReason::EndpointRequest,
255             rf::DeactivateReason::RfLinkLoss => nci::DeactivationReason::RfLinkLoss,
256             rf::DeactivateReason::NfcBBadAfi => nci::DeactivationReason::NfcBBadAfi,
257             rf::DeactivateReason::DhRequestFailed => nci::DeactivationReason::DhRequestFailed,
258         }
259     }
260 }
261