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