• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //! Implementation of the NFCC.
16 
17 use crate::crc;
18 use crate::packets::{nci, rf};
19 use anyhow::Result;
20 use core::time::Duration;
21 use futures::StreamExt;
22 use log::{debug, info, trace, warn};
23 use pdl_runtime::Packet;
24 use std::convert::TryFrom;
25 use std::future::Future;
26 use std::pin::pin;
27 use std::time::Instant;
28 use tokio::sync::mpsc;
29 use tokio::time;
30 
31 const NCI_VERSION: nci::NciVersion = nci::NciVersion::Version20;
32 const MANUFACTURER_ID: u8 = 0x02;
33 const MANUFACTURER_SPECIFIC_INFORMATION: [u8; 26] =
34     [5, 3, 3, 19, 4, 25, 1, 7, 0, 0, 68, 100, 214, 0, 0, 90, 172, 0, 0, 0, 1, 44, 176, 153, 243, 0];
35 
36 /// Read-only configuration parameters
37 const PB_ATTRIB_PARAM1: u8 = 0x00;
38 const LF_T3T_MAX: u8 = 16;
39 const LLCP_VERSION: u8 = 0x00;
40 
41 /// Writable configuration parameters with default
42 /// value defined by the NFCC.
43 const TOTAL_DURATION: u16 = 1000;
44 const PA_DEVICES_LIMIT: u8 = 255;
45 const PB_DEVICES_LIMIT: u8 = 255;
46 const PF_DEVICES_LIMIT: u8 = 255;
47 const PV_DEVICES_LIMIT: u8 = 255;
48 const LA_BIT_FRAME_SDD: u8 = 0x10;
49 const LA_PLATFORM_CONFIG: u8 = 0x0c;
50 const LA_SEL_INFO: u8 = 0x60; // Supports ISO-DEP and NFC-DEP.
51 const LB_SENSB_INFO: u8 = 0x1; // Supports ISO-DEP.
52 const LB_SFGI: u8 = 0;
53 const LB_FWI_ADC_FO: u8 = 0x00;
54 const LF_PROTOCOL_TYPE: u8 = 0x02; // Supports NFC-DEP.
55 const LI_A_RATS_TB1: u8 = 0x70;
56 const LI_A_RATS_TC1: u8 = 0x02;
57 
58 const MAX_LOGICAL_CONNECTIONS: u8 = 2;
59 const MAX_ROUTING_TABLE_SIZE: u16 = 512;
60 const MAX_CONTROL_PACKET_PAYLOAD_SIZE: u8 = 255;
61 const MAX_DATA_PACKET_PAYLOAD_SIZE: u8 = 255;
62 const NUMBER_OF_CREDITS: u8 = 1;
63 const MAX_NFCV_RF_FRAME_SIZE: u16 = 512;
64 const NUMBER_OF_SUPPORTED_EXIT_FRAMES: u8 = 5;
65 const EXIT_FRAME_QUALIFIER_TECHNOLOGY_MASK: u8 = 0b00000011;
66 const EXIT_FRAME_QUALIFIER_PREFIX_MATCHING_MASK: u8 = 0b00010000;
67 
68 /// Time in milliseconds that Casimir waits for poll responses after
69 /// sending a poll command.
70 const POLL_RESPONSE_TIMEOUT: u64 = 200;
71 
72 /// All configuration parameters of the NFCC.
73 /// The configuration is filled with default values from the specification
74 /// See [NCI] Table 46: Common Parameters for Discovery Configuration
75 /// for the format of each parameter and the default value.
76 #[derive(Clone, Debug, PartialEq, Eq)]
77 #[allow(missing_docs)]
78 pub struct ConfigParameters {
79     total_duration: u16,
80     /// [NCI] Table 47: Values for CON_DISCOVERY_PARAM.
81     con_discovery_param: u8,
82     power_state: u8,
83     pa_bail_out: u8,
84     pa_devices_limit: u8,
85     pb_afi: u8,
86     pb_bail_out: u8,
87     pb_attrib_param1: u8,
88     /// [NCI] Table 26: Values for PB_SENSB_REQ_PARAM.
89     pb_sensb_req_param: u8,
90     pb_devices_limit: u8,
91     pf_bit_rate: u8,
92     pf_bail_out: u8,
93     pf_devices_limit: u8,
94     pi_b_h_info: Vec<u8>,
95     pi_bit_rate: u8,
96     pn_nfc_dep_psl: u8,
97     pn_atr_req_gen_bytes: Vec<u8>,
98     /// [NCI] Table 30: Values for PN_ATR_REQ_CONFIG.
99     pn_atr_req_config: u8,
100     pv_devices_limit: u8,
101     la_bit_frame_sdd: u8,
102     la_platform_config: u8,
103     /// [NCI] Table 34: LA_SEL_INFO Coding.
104     la_sel_info: u8,
105     la_nfcid1: Vec<u8>,
106     /// [NCI] Table 36: LB_SENSB_INFO Values.
107     lb_sensb_info: u8,
108     lb_nfcid0: [u8; 4],
109     lb_application_data: u32,
110     lb_sfgi: u8,
111     /// [NCI] Table 37: LB_FWI_ADC_FO Values.
112     lb_fwi_adc_fo: u8,
113     lb_bit_rate: u8,
114     lf_t3t_identifiers_1: [u8; 18],
115     lf_t3t_identifiers_2: [u8; 18],
116     lf_t3t_identifiers_3: [u8; 18],
117     lf_t3t_identifiers_4: [u8; 18],
118     lf_t3t_identifiers_5: [u8; 18],
119     lf_t3t_identifiers_6: [u8; 18],
120     lf_t3t_identifiers_7: [u8; 18],
121     lf_t3t_identifiers_8: [u8; 18],
122     lf_t3t_identifiers_9: [u8; 18],
123     lf_t3t_identifiers_10: [u8; 18],
124     lf_t3t_identifiers_11: [u8; 18],
125     lf_t3t_identifiers_12: [u8; 18],
126     lf_t3t_identifiers_13: [u8; 18],
127     lf_t3t_identifiers_14: [u8; 18],
128     lf_t3t_identifiers_15: [u8; 18],
129     lf_t3t_identifiers_16: [u8; 18],
130     lf_t3t_pmm_default: [u8; 8],
131     lf_t3t_max: u8,
132     lf_t3t_flags: u16,
133     lf_t3t_rd_allowed: u8,
134     /// [NCI] Table 39: Supported Protocols for Listen F.
135     lf_protocol_type: u8,
136     li_a_rats_tb1: u8,
137     li_a_hist_by: Vec<u8>,
138     li_b_h_info_resp: Vec<u8>,
139     li_a_bit_rate: u8,
140     li_a_rats_tc1: u8,
141     ln_wt: u8,
142     ln_atr_res_gen_bytes: Vec<u8>,
143     ln_atr_res_config: u8,
144     pacm_bit_rate: u8,
145     /// [NCI] Table 23: RF Field Information Configuration Parameter.
146     rf_field_info: u8,
147     rf_nfcee_action: u8,
148     nfcdep_op: u8,
149     /// [NCI] Table 115: LLCP Version Parameter.
150     llcp_version: u8,
151     /// [NCI] Table 65: Value Field for NFCC Configuration Control.
152     nfcc_config_control: u8,
153 }
154 
155 /// State of an NFCC logical connection with the DH.
156 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
157 #[allow(missing_docs)]
158 pub enum LogicalConnection {
159     RemoteNfcEndpoint { rf_discovery_id: u8, rf_protocol_type: nci::RfProtocolType },
160 }
161 
162 /// State of the RF Discovery of an NFCC instance.
163 /// The state WaitForAllDiscoveries is not represented as it is implied
164 /// by the discovery routine.
165 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
166 #[allow(missing_docs)]
167 pub enum RfState {
168     Idle,
169     Discovery,
170     PollActive {
171         id: u16,
172         rf_interface: nci::RfInterfaceType,
173         rf_technology: rf::Technology,
174         rf_protocol: rf::Protocol,
175     },
176     ListenSleep {
177         id: u16,
178     },
179     ListenActive {
180         id: u16,
181         rf_interface: nci::RfInterfaceType,
182         rf_technology: rf::Technology,
183         rf_protocol: rf::Protocol,
184     },
185     WaitForHostSelect,
186     WaitForSelectResponse {
187         id: u16,
188         rf_discovery_id: usize,
189         rf_interface: nci::RfInterfaceType,
190         rf_technology: rf::Technology,
191         rf_protocol: rf::Protocol,
192     },
193 }
194 
195 /// State of the emulated eSE (ST) NFCEE.
196 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
197 #[allow(missing_docs)]
198 pub enum NfceeState {
199     Enabled,
200     Disabled,
201 }
202 
203 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
204 #[allow(missing_docs)]
205 pub enum RfMode {
206     Poll,
207     Listen,
208 }
209 
210 /// Poll responses received in the context of RF discovery in active
211 /// Listen mode.
212 #[derive(Clone, Debug, PartialEq, Eq)]
213 pub struct RfPollResponse {
214     id: u16,
215     rf_protocol: rf::Protocol,
216     rf_technology: rf::Technology,
217     rf_technology_specific_parameters: Vec<u8>,
218 }
219 
220 /// Exit frame data received by the Set exit frame command.
221 #[derive(Clone, Debug, PartialEq, Eq)]
222 pub struct RfExitFrame {
223     is_prefix_matching_allowed: bool,
224     rf_technology: rf::Technology,
225     power_states: u8,
226     data: Vec<u8>,
227     mask: Vec<u8>,
228 }
229 
230 /// State of an NFCC instance.
231 #[allow(missing_docs)]
232 pub struct State {
233     pub config_parameters: ConfigParameters,
234     pub logical_connections: [Option<LogicalConnection>; MAX_LOGICAL_CONNECTIONS as usize],
235     pub discover_configuration: Vec<nci::DiscoverConfiguration>,
236     pub discover_map: Vec<nci::MappingConfiguration>,
237     pub nfcee_state: NfceeState,
238     pub rf_state: RfState,
239     pub rf_poll_responses: Vec<RfPollResponse>,
240     pub rf_activation_parameters: Vec<u8>,
241     // TODO(johnrjohn) Use bitflags here
242     pub passive_observe_mode: u8,
243     pub last_observe_mode_state: Option<u8>,
244     pub start_time: std::time::Instant,
245     pub remote_field_status: rf::FieldStatus,
246     pub exit_frame_timeout: Duration,
247     pub exit_frame_start_time: Option<std::time::Instant>,
248     pub exit_frames: Vec<RfExitFrame>,
249 }
250 
251 /// State of an NFCC instance.
252 pub struct Controller<'a> {
253     id: u16,
254     nci_stream: nci::StreamRefMut<'a>,
255     nci_writer: nci::Writer,
256     rf_rx: mpsc::UnboundedReceiver<rf::RfPacket>,
257     rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
258     state: State,
259 }
260 
261 impl ConfigParameters {
get(&self, id: nci::ConfigParameterId) -> Result<Vec<u8>>262     fn get(&self, id: nci::ConfigParameterId) -> Result<Vec<u8>> {
263         match id {
264             nci::ConfigParameterId::TotalDuration => Ok(self.total_duration.to_le_bytes().to_vec()),
265             nci::ConfigParameterId::ConDiscoveryParam => {
266                 Ok(self.con_discovery_param.to_le_bytes().to_vec())
267             }
268             nci::ConfigParameterId::PowerState => Ok(vec![self.power_state]),
269             nci::ConfigParameterId::PaBailOut => Ok(vec![self.pa_bail_out]),
270             nci::ConfigParameterId::PaDevicesLimit => Ok(vec![self.pa_devices_limit]),
271             nci::ConfigParameterId::PbAfi => Ok(vec![self.pb_afi]),
272             nci::ConfigParameterId::PbBailOut => Ok(vec![self.pb_bail_out]),
273             nci::ConfigParameterId::PbAttribParam1 => Ok(vec![self.pb_attrib_param1]),
274             nci::ConfigParameterId::PbSensbReqParam => Ok(vec![self.pb_sensb_req_param]),
275             nci::ConfigParameterId::PbDevicesLimit => Ok(vec![self.pb_devices_limit]),
276             nci::ConfigParameterId::PfBitRate => Ok(vec![self.pf_bit_rate]),
277             nci::ConfigParameterId::PfBailOut => Ok(vec![self.pf_bail_out]),
278             nci::ConfigParameterId::PfDevicesLimit => Ok(vec![self.pf_devices_limit]),
279             nci::ConfigParameterId::PiBHInfo => Ok(self.pi_b_h_info.clone()),
280             nci::ConfigParameterId::PiBitRate => Ok(vec![self.pi_bit_rate]),
281             nci::ConfigParameterId::PnNfcDepPsl => Ok(vec![self.pn_nfc_dep_psl]),
282             nci::ConfigParameterId::PnAtrReqGenBytes => Ok(self.pn_atr_req_gen_bytes.clone()),
283             nci::ConfigParameterId::PnAtrReqConfig => Ok(vec![self.pn_atr_req_config]),
284             nci::ConfigParameterId::PvDevicesLimit => Ok(vec![self.pv_devices_limit]),
285             nci::ConfigParameterId::LaBitFrameSdd => Ok(vec![self.la_bit_frame_sdd]),
286             nci::ConfigParameterId::LaPlatformConfig => Ok(vec![self.la_platform_config]),
287             nci::ConfigParameterId::LaSelInfo => Ok(vec![self.la_sel_info]),
288             nci::ConfigParameterId::LaNfcid1 => Ok(self.la_nfcid1.clone()),
289             nci::ConfigParameterId::LbSensbInfo => Ok(vec![self.lb_sensb_info]),
290             nci::ConfigParameterId::LbNfcid0 => Ok(self.lb_nfcid0.to_vec()),
291             nci::ConfigParameterId::LbApplicationData => {
292                 Ok(self.lb_application_data.to_le_bytes().to_vec())
293             }
294             nci::ConfigParameterId::LbSfgi => Ok(vec![self.lb_sfgi]),
295             nci::ConfigParameterId::LbFwiAdcFo => Ok(vec![self.lb_fwi_adc_fo]),
296             nci::ConfigParameterId::LbBitRate => Ok(vec![self.lb_bit_rate]),
297             nci::ConfigParameterId::LfT3tIdentifiers1 => Ok(self.lf_t3t_identifiers_1.to_vec()),
298             nci::ConfigParameterId::LfT3tIdentifiers2 => Ok(self.lf_t3t_identifiers_2.to_vec()),
299             nci::ConfigParameterId::LfT3tIdentifiers3 => Ok(self.lf_t3t_identifiers_3.to_vec()),
300             nci::ConfigParameterId::LfT3tIdentifiers4 => Ok(self.lf_t3t_identifiers_4.to_vec()),
301             nci::ConfigParameterId::LfT3tIdentifiers5 => Ok(self.lf_t3t_identifiers_5.to_vec()),
302             nci::ConfigParameterId::LfT3tIdentifiers6 => Ok(self.lf_t3t_identifiers_6.to_vec()),
303             nci::ConfigParameterId::LfT3tIdentifiers7 => Ok(self.lf_t3t_identifiers_7.to_vec()),
304             nci::ConfigParameterId::LfT3tIdentifiers8 => Ok(self.lf_t3t_identifiers_8.to_vec()),
305             nci::ConfigParameterId::LfT3tIdentifiers9 => Ok(self.lf_t3t_identifiers_9.to_vec()),
306             nci::ConfigParameterId::LfT3tIdentifiers10 => Ok(self.lf_t3t_identifiers_10.to_vec()),
307             nci::ConfigParameterId::LfT3tIdentifiers11 => Ok(self.lf_t3t_identifiers_11.to_vec()),
308             nci::ConfigParameterId::LfT3tIdentifiers12 => Ok(self.lf_t3t_identifiers_12.to_vec()),
309             nci::ConfigParameterId::LfT3tIdentifiers13 => Ok(self.lf_t3t_identifiers_13.to_vec()),
310             nci::ConfigParameterId::LfT3tIdentifiers14 => Ok(self.lf_t3t_identifiers_14.to_vec()),
311             nci::ConfigParameterId::LfT3tIdentifiers15 => Ok(self.lf_t3t_identifiers_15.to_vec()),
312             nci::ConfigParameterId::LfT3tIdentifiers16 => Ok(self.lf_t3t_identifiers_16.to_vec()),
313             nci::ConfigParameterId::LfT3tPmmDefault => Ok(self.lf_t3t_pmm_default.to_vec()),
314             nci::ConfigParameterId::LfT3tMax => Ok(vec![self.lf_t3t_max]),
315             nci::ConfigParameterId::LfT3tFlags => Ok(self.lf_t3t_flags.to_le_bytes().to_vec()),
316             nci::ConfigParameterId::LfT3tRdAllowed => Ok(vec![self.lf_t3t_rd_allowed]),
317             nci::ConfigParameterId::LfProtocolType => Ok(vec![self.lf_protocol_type]),
318             nci::ConfigParameterId::LiARatsTb1 => Ok(vec![self.li_a_rats_tb1]),
319             nci::ConfigParameterId::LiAHistBy => Ok(self.li_a_hist_by.clone()),
320             nci::ConfigParameterId::LiBHInfoResp => Ok(self.li_b_h_info_resp.clone()),
321             nci::ConfigParameterId::LiABitRate => Ok(vec![self.li_a_bit_rate]),
322             nci::ConfigParameterId::LiARatsTc1 => Ok(vec![self.li_a_rats_tc1]),
323             nci::ConfigParameterId::LnWt => Ok(vec![self.ln_wt]),
324             nci::ConfigParameterId::LnAtrResGenBytes => Ok(self.ln_atr_res_gen_bytes.clone()),
325             nci::ConfigParameterId::LnAtrResConfig => Ok(vec![self.ln_atr_res_config]),
326             nci::ConfigParameterId::PacmBitRate => Ok(vec![self.pacm_bit_rate]),
327             nci::ConfigParameterId::RfFieldInfo => Ok(vec![self.rf_field_info]),
328             nci::ConfigParameterId::RfNfceeAction => Ok(vec![self.rf_nfcee_action]),
329             nci::ConfigParameterId::NfcdepOp => Ok(vec![self.nfcdep_op]),
330             nci::ConfigParameterId::LlcpVersion => Ok(vec![self.llcp_version]),
331             nci::ConfigParameterId::NfccConfigControl => Ok(vec![self.nfcc_config_control]),
332             _ => Err(anyhow::anyhow!("unknown config parameter ID")),
333         }
334     }
335 
set(&mut self, id: nci::ConfigParameterId, value: &[u8]) -> Result<()>336     fn set(&mut self, id: nci::ConfigParameterId, value: &[u8]) -> Result<()> {
337         match id {
338             nci::ConfigParameterId::TotalDuration => {
339                 self.total_duration = u16::from_le_bytes(value.try_into()?);
340                 Ok(())
341             }
342             nci::ConfigParameterId::ConDiscoveryParam => {
343                 self.con_discovery_param = u8::from_le_bytes(value.try_into()?);
344                 Ok(())
345             }
346             nci::ConfigParameterId::PowerState => {
347                 self.power_state = u8::from_le_bytes(value.try_into()?);
348                 Ok(())
349             }
350             nci::ConfigParameterId::PaBailOut => {
351                 self.pa_bail_out = u8::from_le_bytes(value.try_into()?);
352                 Ok(())
353             }
354             nci::ConfigParameterId::PaDevicesLimit => {
355                 self.pa_devices_limit = u8::from_le_bytes(value.try_into()?);
356                 Ok(())
357             }
358             nci::ConfigParameterId::PbAfi => {
359                 self.pb_afi = u8::from_le_bytes(value.try_into()?);
360                 Ok(())
361             }
362             nci::ConfigParameterId::PbBailOut => {
363                 self.pb_bail_out = u8::from_le_bytes(value.try_into()?);
364                 Ok(())
365             }
366             nci::ConfigParameterId::PbAttribParam1 => {
367                 self.pb_attrib_param1 = u8::from_le_bytes(value.try_into()?);
368                 Ok(())
369             }
370             nci::ConfigParameterId::PbSensbReqParam => {
371                 self.pb_sensb_req_param = u8::from_le_bytes(value.try_into()?);
372                 Ok(())
373             }
374             nci::ConfigParameterId::PbDevicesLimit => {
375                 self.pb_devices_limit = u8::from_le_bytes(value.try_into()?);
376                 Ok(())
377             }
378             nci::ConfigParameterId::PfBitRate => {
379                 self.pf_bit_rate = u8::from_le_bytes(value.try_into()?);
380                 Ok(())
381             }
382             nci::ConfigParameterId::PfBailOut => {
383                 self.pf_bail_out = u8::from_le_bytes(value.try_into()?);
384                 Ok(())
385             }
386             nci::ConfigParameterId::PfDevicesLimit => {
387                 self.pf_devices_limit = u8::from_le_bytes(value.try_into()?);
388                 Ok(())
389             }
390             nci::ConfigParameterId::PiBHInfo => {
391                 self.pi_b_h_info = value.to_vec();
392                 Ok(())
393             }
394             nci::ConfigParameterId::PiBitRate => {
395                 self.pi_bit_rate = u8::from_le_bytes(value.try_into()?);
396                 Ok(())
397             }
398             nci::ConfigParameterId::PnNfcDepPsl => {
399                 self.pn_nfc_dep_psl = u8::from_le_bytes(value.try_into()?);
400                 Ok(())
401             }
402             nci::ConfigParameterId::PnAtrReqGenBytes => {
403                 self.pn_atr_req_gen_bytes = value.to_vec();
404                 Ok(())
405             }
406             nci::ConfigParameterId::PnAtrReqConfig => {
407                 self.pn_atr_req_config = u8::from_le_bytes(value.try_into()?);
408                 Ok(())
409             }
410             nci::ConfigParameterId::PvDevicesLimit => {
411                 self.pv_devices_limit = u8::from_le_bytes(value.try_into()?);
412                 Ok(())
413             }
414             nci::ConfigParameterId::LaBitFrameSdd => {
415                 self.la_bit_frame_sdd = u8::from_le_bytes(value.try_into()?);
416                 Ok(())
417             }
418             nci::ConfigParameterId::LaPlatformConfig => {
419                 self.la_platform_config = u8::from_le_bytes(value.try_into()?);
420                 Ok(())
421             }
422             nci::ConfigParameterId::LaSelInfo => {
423                 self.la_sel_info = u8::from_le_bytes(value.try_into()?);
424                 Ok(())
425             }
426             nci::ConfigParameterId::LaNfcid1 => {
427                 self.la_nfcid1 = value.to_vec();
428                 Ok(())
429             }
430             nci::ConfigParameterId::LbSensbInfo => {
431                 self.lb_sensb_info = u8::from_le_bytes(value.try_into()?);
432                 Ok(())
433             }
434             nci::ConfigParameterId::LbNfcid0 => {
435                 self.lb_nfcid0 = value.try_into()?;
436                 Ok(())
437             }
438             nci::ConfigParameterId::LbApplicationData => {
439                 self.lb_application_data = u32::from_le_bytes(value.try_into()?);
440                 Ok(())
441             }
442             nci::ConfigParameterId::LbSfgi => {
443                 self.lb_sfgi = u8::from_le_bytes(value.try_into()?);
444                 Ok(())
445             }
446             nci::ConfigParameterId::LbFwiAdcFo => {
447                 self.lb_fwi_adc_fo = u8::from_le_bytes(value.try_into()?);
448                 Ok(())
449             }
450             nci::ConfigParameterId::LbBitRate => {
451                 self.lb_bit_rate = u8::from_le_bytes(value.try_into()?);
452                 Ok(())
453             }
454             nci::ConfigParameterId::LfT3tIdentifiers1 => {
455                 self.lf_t3t_identifiers_1 = value.try_into()?;
456                 Ok(())
457             }
458             nci::ConfigParameterId::LfT3tIdentifiers2 => {
459                 self.lf_t3t_identifiers_2 = value.try_into()?;
460                 Ok(())
461             }
462             nci::ConfigParameterId::LfT3tIdentifiers3 => {
463                 self.lf_t3t_identifiers_3 = value.try_into()?;
464                 Ok(())
465             }
466             nci::ConfigParameterId::LfT3tIdentifiers4 => {
467                 self.lf_t3t_identifiers_4 = value.try_into()?;
468                 Ok(())
469             }
470             nci::ConfigParameterId::LfT3tIdentifiers5 => {
471                 self.lf_t3t_identifiers_5 = value.try_into()?;
472                 Ok(())
473             }
474             nci::ConfigParameterId::LfT3tIdentifiers6 => {
475                 self.lf_t3t_identifiers_6 = value.try_into()?;
476                 Ok(())
477             }
478             nci::ConfigParameterId::LfT3tIdentifiers7 => {
479                 self.lf_t3t_identifiers_7 = value.try_into()?;
480                 Ok(())
481             }
482             nci::ConfigParameterId::LfT3tIdentifiers8 => {
483                 self.lf_t3t_identifiers_8 = value.try_into()?;
484                 Ok(())
485             }
486             nci::ConfigParameterId::LfT3tIdentifiers9 => {
487                 self.lf_t3t_identifiers_9 = value.try_into()?;
488                 Ok(())
489             }
490             nci::ConfigParameterId::LfT3tIdentifiers10 => {
491                 self.lf_t3t_identifiers_10 = value.try_into()?;
492                 Ok(())
493             }
494             nci::ConfigParameterId::LfT3tIdentifiers11 => {
495                 self.lf_t3t_identifiers_11 = value.try_into()?;
496                 Ok(())
497             }
498             nci::ConfigParameterId::LfT3tIdentifiers12 => {
499                 self.lf_t3t_identifiers_12 = value.try_into()?;
500                 Ok(())
501             }
502             nci::ConfigParameterId::LfT3tIdentifiers13 => {
503                 self.lf_t3t_identifiers_13 = value.try_into()?;
504                 Ok(())
505             }
506             nci::ConfigParameterId::LfT3tIdentifiers14 => {
507                 self.lf_t3t_identifiers_14 = value.try_into()?;
508                 Ok(())
509             }
510             nci::ConfigParameterId::LfT3tIdentifiers15 => {
511                 self.lf_t3t_identifiers_15 = value.try_into()?;
512                 Ok(())
513             }
514             nci::ConfigParameterId::LfT3tIdentifiers16 => {
515                 self.lf_t3t_identifiers_16 = value.try_into()?;
516                 Ok(())
517             }
518             nci::ConfigParameterId::LfT3tPmmDefault => {
519                 self.lf_t3t_pmm_default = value.try_into()?;
520                 Ok(())
521             }
522             nci::ConfigParameterId::LfT3tMax => Err(anyhow::anyhow!("read-only config parameter")),
523             nci::ConfigParameterId::LfT3tFlags => {
524                 self.lf_t3t_flags = u16::from_le_bytes(value.try_into()?);
525                 Ok(())
526             }
527             nci::ConfigParameterId::LfT3tRdAllowed => {
528                 self.lf_t3t_rd_allowed = u8::from_le_bytes(value.try_into()?);
529                 Ok(())
530             }
531             nci::ConfigParameterId::LfProtocolType => {
532                 self.lf_protocol_type = u8::from_le_bytes(value.try_into()?);
533                 Ok(())
534             }
535             nci::ConfigParameterId::LiARatsTb1 => {
536                 self.li_a_rats_tb1 = u8::from_le_bytes(value.try_into()?);
537                 Ok(())
538             }
539             nci::ConfigParameterId::LiAHistBy => {
540                 self.li_a_hist_by = value.to_vec();
541                 Ok(())
542             }
543             nci::ConfigParameterId::LiBHInfoResp => {
544                 self.li_b_h_info_resp = value.to_vec();
545                 Ok(())
546             }
547             nci::ConfigParameterId::LiABitRate => {
548                 self.li_a_bit_rate = u8::from_le_bytes(value.try_into()?);
549                 Ok(())
550             }
551             nci::ConfigParameterId::LiARatsTc1 => {
552                 self.li_a_rats_tc1 = u8::from_le_bytes(value.try_into()?);
553                 Ok(())
554             }
555             nci::ConfigParameterId::LnWt => {
556                 self.ln_wt = u8::from_le_bytes(value.try_into()?);
557                 Ok(())
558             }
559             nci::ConfigParameterId::LnAtrResGenBytes => {
560                 self.ln_atr_res_gen_bytes = value.to_vec();
561                 Ok(())
562             }
563             nci::ConfigParameterId::LnAtrResConfig => {
564                 self.ln_atr_res_config = u8::from_le_bytes(value.try_into()?);
565                 Ok(())
566             }
567             nci::ConfigParameterId::PacmBitRate => {
568                 self.pacm_bit_rate = u8::from_le_bytes(value.try_into()?);
569                 Ok(())
570             }
571             nci::ConfigParameterId::RfFieldInfo => {
572                 self.rf_field_info = u8::from_le_bytes(value.try_into()?);
573                 Ok(())
574             }
575             nci::ConfigParameterId::RfNfceeAction => {
576                 self.rf_nfcee_action = u8::from_le_bytes(value.try_into()?);
577                 Ok(())
578             }
579             nci::ConfigParameterId::NfcdepOp => {
580                 self.nfcdep_op = u8::from_le_bytes(value.try_into()?);
581                 Ok(())
582             }
583             nci::ConfigParameterId::LlcpVersion => {
584                 self.llcp_version = u8::from_le_bytes(value.try_into()?);
585                 Ok(())
586             }
587             nci::ConfigParameterId::NfccConfigControl => {
588                 self.nfcc_config_control = u8::from_le_bytes(value.try_into()?);
589                 Ok(())
590             }
591             _ => Err(anyhow::anyhow!("unknown config parameter ID")),
592         }
593     }
594 }
595 
596 impl Default for ConfigParameters {
default() -> Self597     fn default() -> Self {
598         ConfigParameters {
599             total_duration: TOTAL_DURATION,
600             con_discovery_param: 0x01,
601             power_state: 0x02,
602             pa_bail_out: 0x00,
603             pa_devices_limit: PA_DEVICES_LIMIT,
604             pb_afi: 0x00,
605             pb_bail_out: 0x00,
606             pb_attrib_param1: PB_ATTRIB_PARAM1,
607             pb_sensb_req_param: 0x00,
608             pb_devices_limit: PB_DEVICES_LIMIT,
609             pf_bit_rate: 0x01,
610             pf_bail_out: 0x00,
611             pf_devices_limit: PF_DEVICES_LIMIT,
612             pi_b_h_info: vec![],
613             pi_bit_rate: 0x00,
614             pn_nfc_dep_psl: 0x00,
615             pn_atr_req_gen_bytes: vec![],
616             pn_atr_req_config: 0x30,
617             pv_devices_limit: PV_DEVICES_LIMIT,
618             la_bit_frame_sdd: LA_BIT_FRAME_SDD,
619             la_platform_config: LA_PLATFORM_CONFIG,
620             la_sel_info: LA_SEL_INFO,
621             la_nfcid1: vec![0x08, 0x00, 0x00, 0x00],
622             lb_sensb_info: LB_SENSB_INFO,
623             lb_nfcid0: [0x08, 0x00, 0x00, 0x00],
624             lb_application_data: 0x00000000,
625             lb_sfgi: LB_SFGI,
626             lb_fwi_adc_fo: LB_FWI_ADC_FO,
627             lb_bit_rate: 0x00,
628             lf_t3t_identifiers_1: [0; 18],
629             lf_t3t_identifiers_2: [0; 18],
630             lf_t3t_identifiers_3: [0; 18],
631             lf_t3t_identifiers_4: [0; 18],
632             lf_t3t_identifiers_5: [0; 18],
633             lf_t3t_identifiers_6: [0; 18],
634             lf_t3t_identifiers_7: [0; 18],
635             lf_t3t_identifiers_8: [0; 18],
636             lf_t3t_identifiers_9: [0; 18],
637             lf_t3t_identifiers_10: [0; 18],
638             lf_t3t_identifiers_11: [0; 18],
639             lf_t3t_identifiers_12: [0; 18],
640             lf_t3t_identifiers_13: [0; 18],
641             lf_t3t_identifiers_14: [0; 18],
642             lf_t3t_identifiers_15: [0; 18],
643             lf_t3t_identifiers_16: [0; 18],
644             lf_t3t_pmm_default: [0xff; 8],
645             lf_t3t_max: LF_T3T_MAX,
646             lf_t3t_flags: 0x0000,
647             lf_t3t_rd_allowed: 0x00,
648             lf_protocol_type: LF_PROTOCOL_TYPE,
649             li_a_rats_tb1: LI_A_RATS_TB1,
650             li_a_hist_by: vec![],
651             li_b_h_info_resp: vec![],
652             li_a_bit_rate: 0x00,
653             li_a_rats_tc1: LI_A_RATS_TC1,
654             ln_wt: 10,
655             ln_atr_res_gen_bytes: vec![],
656             ln_atr_res_config: 0x30,
657             pacm_bit_rate: 0x01,
658             rf_field_info: 0x00,
659             rf_nfcee_action: 0x01,
660             // [NCI] Table 101: NFC-DEP Operation Parameter.
661             nfcdep_op: 0x1f,
662             llcp_version: LLCP_VERSION,
663             nfcc_config_control: 0x00,
664         }
665     }
666 }
667 
668 impl State {
669     /// Craft the NFCID1 used by this instance in NFC-A poll responses.
670     /// Returns a dynamically generated NFCID1 (4 byte long and starts with 08h).
nfcid1(&self) -> Vec<u8>671     fn nfcid1(&self) -> Vec<u8> {
672         if self.config_parameters.la_nfcid1.len() == 4
673             && self.config_parameters.la_nfcid1[0] == 0x08
674         {
675             vec![0x08, 186, 7, 99] // TODO(hchataing) pseudo random
676         } else {
677             self.config_parameters.la_nfcid1.clone()
678         }
679     }
680 
681     /// Select the interface to be preferably used for the selected protocol.
select_interface( &self, mode: RfMode, rf_protocol: nci::RfProtocolType, ) -> nci::RfInterfaceType682     fn select_interface(
683         &self,
684         mode: RfMode,
685         rf_protocol: nci::RfProtocolType,
686     ) -> nci::RfInterfaceType {
687         for config in self.discover_map.iter() {
688             match (mode, config.mode.poll_mode, config.mode.listen_mode) {
689                 _ if config.rf_protocol != rf_protocol => (),
690                 (RfMode::Poll, nci::FeatureFlag::Enabled, _)
691                 | (RfMode::Listen, _, nci::FeatureFlag::Enabled) => return config.rf_interface,
692                 _ => (),
693             }
694         }
695 
696         // [NCI] 6.2 RF Interface Mapping Configuration
697         //
698         // The NFCC SHALL set the default mapping of RF Interface to RF Protocols /
699         // Modes to the following values:
700         //
701         // • If the NFCC supports the ISO-DEP RF interface, the NFCC SHALL map the
702         //   ISO-DEP RF Protocol to the ISO-DEP RF Interface for Poll Mode and
703         //   Listen Mode.
704         // • If the NFCC supports the NFC-DEP RF interface, the NFCC SHALL map the
705         //   NFC-DEP RF Protocol to the NFC-DEP RF Interface for Poll Mode and
706         //   Listen Mode.
707         // • If the NFCC supports the NDEF RF interface, the NFCC SHALL map the
708         //   NDEF RF Protocol to the NDEF RF Interface for Poll Mode.
709         // • Otherwise, the NFCC SHALL map to the Frame RF Interface by default
710         match rf_protocol {
711             nci::RfProtocolType::IsoDep => nci::RfInterfaceType::IsoDep,
712             nci::RfProtocolType::NfcDep => nci::RfInterfaceType::NfcDep,
713             nci::RfProtocolType::Ndef if mode == RfMode::Poll => nci::RfInterfaceType::Ndef,
714             _ => nci::RfInterfaceType::Frame,
715         }
716     }
717 
718     /// Insert a poll response into the discovery list.
719     /// The response is not inserted if the device was already discovered
720     /// with the same parameters.
add_poll_response(&mut self, poll_response: RfPollResponse)721     fn add_poll_response(&mut self, poll_response: RfPollResponse) {
722         if !self.rf_poll_responses.contains(&poll_response) {
723             self.rf_poll_responses.push(poll_response);
724         }
725     }
726 }
727 
728 impl<'a> Controller<'a> {
729     /// Create a new NFCC instance with default configuration.
new( id: u16, nci_stream: nci::StreamRefMut<'a>, nci_writer: nci::Writer, rf_rx: mpsc::UnboundedReceiver<rf::RfPacket>, rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Controller<'a>730     pub fn new(
731         id: u16,
732         nci_stream: nci::StreamRefMut<'a>,
733         nci_writer: nci::Writer,
734         rf_rx: mpsc::UnboundedReceiver<rf::RfPacket>,
735         rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
736     ) -> Controller<'a> {
737         Controller {
738             id,
739             nci_stream,
740             nci_writer,
741             rf_rx,
742             rf_tx,
743             state: State {
744                 config_parameters: Default::default(),
745                 logical_connections: [None; MAX_LOGICAL_CONNECTIONS as usize],
746                 discover_map: vec![],
747                 discover_configuration: vec![],
748                 nfcee_state: NfceeState::Disabled,
749                 rf_state: RfState::Idle,
750                 rf_poll_responses: vec![],
751                 rf_activation_parameters: vec![],
752                 passive_observe_mode: nci::PassiveObserveMode::Disable.into(),
753                 last_observe_mode_state: None,
754                 start_time: Instant::now(),
755                 remote_field_status: rf::FieldStatus::FieldOff,
756                 exit_frame_timeout: Duration::from_millis(0),
757                 exit_frame_start_time: None,
758                 exit_frames: vec![],
759             },
760         }
761     }
762 
send_control(&mut self, packet: impl Into<nci::ControlPacket>) -> Result<()>763     async fn send_control(&mut self, packet: impl Into<nci::ControlPacket>) -> Result<()> {
764         self.nci_writer.write(&packet.into().encode_to_vec()?).await
765     }
766 
send_data(&mut self, packet: impl Into<nci::DataPacket>) -> Result<()>767     async fn send_data(&mut self, packet: impl Into<nci::DataPacket>) -> Result<()> {
768         self.nci_writer.write(&packet.into().encode_to_vec()?).await
769     }
770 
send_rf(&self, packet: impl Into<rf::RfPacket>) -> Result<()>771     async fn send_rf(&self, packet: impl Into<rf::RfPacket>) -> Result<()> {
772         self.rf_tx.send(packet.into())?;
773         Ok(())
774     }
775 
core_reset(&mut self, cmd: nci::CoreResetCommand) -> Result<()>776     async fn core_reset(&mut self, cmd: nci::CoreResetCommand) -> Result<()> {
777         info!("[{}] CORE_RESET_CMD", self.id);
778         info!("         ResetType: {:?}", cmd.get_reset_type());
779 
780         match cmd.get_reset_type() {
781             nci::ResetType::KeepConfig => (),
782             nci::ResetType::ResetConfig => self.state.config_parameters = Default::default(),
783         }
784 
785         for i in 0..MAX_LOGICAL_CONNECTIONS {
786             self.state.logical_connections[i as usize] = None;
787         }
788 
789         self.state.discover_map.clear();
790         self.state.discover_configuration.clear();
791         self.state.rf_state = RfState::Idle;
792         self.state.rf_poll_responses.clear();
793 
794         self.send_control(nci::CoreResetResponseBuilder { status: nci::Status::Ok }).await?;
795 
796         self.send_control(nci::CoreResetNotificationBuilder {
797             trigger: nci::ResetTrigger::ResetCommand,
798             config_status: match cmd.get_reset_type() {
799                 nci::ResetType::KeepConfig => nci::ConfigStatus::ConfigKept,
800                 nci::ResetType::ResetConfig => nci::ConfigStatus::ConfigReset,
801             },
802             nci_version: NCI_VERSION,
803             manufacturer_id: MANUFACTURER_ID,
804             manufacturer_specific_information: MANUFACTURER_SPECIFIC_INFORMATION.to_vec(),
805         })
806         .await?;
807 
808         Ok(())
809     }
810 
core_init(&mut self, _cmd: nci::CoreInitCommand) -> Result<()>811     async fn core_init(&mut self, _cmd: nci::CoreInitCommand) -> Result<()> {
812         info!("[{}] CORE_INIT_CMD", self.id);
813 
814         self.send_control(nci::CoreInitResponseBuilder {
815             status: nci::Status::Ok,
816             nfcc_features: nci::NfccFeatures {
817                 discovery_frequency_configuration: nci::FeatureFlag::Disabled,
818                 discovery_configuration_mode: nci::DiscoveryConfigurationMode::DhOnly,
819                 hci_network_support: nci::FeatureFlag::Enabled,
820                 active_communication_mode: nci::FeatureFlag::Enabled,
821                 technology_based_routing: nci::FeatureFlag::Enabled,
822                 protocol_based_routing: nci::FeatureFlag::Enabled,
823                 aid_based_routing: nci::FeatureFlag::Enabled,
824                 system_code_based_routing: nci::FeatureFlag::Enabled,
825                 apdu_pattern_based_routing: nci::FeatureFlag::Enabled,
826                 forced_nfcee_routing: nci::FeatureFlag::Enabled,
827                 battery_off_state: nci::FeatureFlag::Disabled,
828                 switched_off_state: nci::FeatureFlag::Enabled,
829                 switched_on_substates: nci::FeatureFlag::Enabled,
830                 rf_configuration_in_switched_off_state: nci::FeatureFlag::Disabled,
831                 proprietary_capabilities: 0,
832             },
833             max_logical_connections: MAX_LOGICAL_CONNECTIONS,
834             max_routing_table_size: MAX_ROUTING_TABLE_SIZE,
835             max_control_packet_payload_size: MAX_CONTROL_PACKET_PAYLOAD_SIZE,
836             max_data_packet_payload_size: MAX_DATA_PACKET_PAYLOAD_SIZE,
837             number_of_credits: NUMBER_OF_CREDITS,
838             max_nfcv_rf_frame_size: MAX_NFCV_RF_FRAME_SIZE,
839             supported_rf_interfaces: vec![
840                 nci::RfInterface { interface: nci::RfInterfaceType::Frame, extensions: vec![] },
841                 nci::RfInterface { interface: nci::RfInterfaceType::IsoDep, extensions: vec![] },
842                 nci::RfInterface { interface: nci::RfInterfaceType::NfcDep, extensions: vec![] },
843                 nci::RfInterface {
844                     interface: nci::RfInterfaceType::NfceeDirect,
845                     extensions: vec![],
846                 },
847             ],
848         })
849         .await?;
850 
851         Ok(())
852     }
853 
core_set_config(&mut self, cmd: nci::CoreSetConfigCommand) -> Result<()>854     async fn core_set_config(&mut self, cmd: nci::CoreSetConfigCommand) -> Result<()> {
855         info!("[{}] CORE_SET_CONFIG_CMD", self.id);
856 
857         let mut invalid_parameters = vec![];
858         for parameter in cmd.get_parameters().iter() {
859             info!("         Type: {:?}", parameter.id);
860             info!("         Value: {:?}", parameter.value);
861             match parameter.id {
862                 nci::ConfigParameterId::Rfu(_) => invalid_parameters.push(parameter.id),
863                 // TODO(henrichataing):
864                 // [NCI] 5.2.1 State RFST_IDLE
865                 // Unless otherwise specified, discovery related configuration
866                 // defined in Sections 6.1, 6.2, 6.3 and 7.1 SHALL only be set
867                 // while in IDLE state.
868                 //
869                 // Respond with Semantic Error as indicated by
870                 // [NCI] 3.2.2 Exception Handling for Control Messages
871                 // An unexpected Command SHALL NOT cause any action by the NFCC.
872                 // Unless otherwise specified, the NFCC SHALL send a Response
873                 // with a Status value of STATUS_SEMANTIC_ERROR and no
874                 // additional fields.
875                 _ => {
876                     if self.state.config_parameters.set(parameter.id, &parameter.value).is_err() {
877                         invalid_parameters.push(parameter.id)
878                     }
879                 }
880             }
881         }
882 
883         self.send_control(nci::CoreSetConfigResponseBuilder {
884             status: if invalid_parameters.is_empty() {
885                 // A Status of STATUS_OK SHALL indicate that all configuration parameters
886                 // have been set to these new values in the NFCC.
887                 nci::Status::Ok
888             } else {
889                 // If the DH tries to set a parameter that is not applicable for the NFCC,
890                 // the NFCC SHALL respond with a CORE_SET_CONFIG_RSP with a Status field
891                 // of STATUS_INVALID_PARAM and including one or more invalid Parameter ID(s).
892                 // All other configuration parameters SHALL have been set to the new values
893                 // in the NFCC.
894                 warn!(
895                     "[{}] rejecting unknown configuration parameter ids: {:?}",
896                     self.id, invalid_parameters
897                 );
898                 nci::Status::InvalidParam
899             },
900             parameters: invalid_parameters,
901         })
902         .await?;
903 
904         Ok(())
905     }
906 
core_get_config(&mut self, cmd: nci::CoreGetConfigCommand) -> Result<()>907     async fn core_get_config(&mut self, cmd: nci::CoreGetConfigCommand) -> Result<()> {
908         info!("[{}] CORE_GET_CONFIG_CMD", self.id);
909 
910         let mut valid_parameters = vec![];
911         let mut invalid_parameters = vec![];
912         for id in cmd.get_parameters() {
913             info!("         ID: {:?}", id);
914             match self.state.config_parameters.get(*id) {
915                 Ok(value) => {
916                     valid_parameters.push(nci::ConfigParameter { id: *id, value: value.to_vec() })
917                 }
918                 Err(_) => invalid_parameters.push(nci::ConfigParameter { id: *id, value: vec![] }),
919             }
920         }
921 
922         self.send_control(if invalid_parameters.is_empty() {
923             // If the NFCC is able to respond with all requested parameters, the
924             // NFCC SHALL respond with the CORE_GET_CONFIG_RSP with a Status
925             // of STATUS_OK.
926             nci::CoreGetConfigResponseBuilder {
927                 status: nci::Status::Ok,
928                 parameters: valid_parameters,
929             }
930         } else {
931             // If the DH tries to retrieve any parameter(s) that are not available
932             // in the NFCC, the NFCC SHALL respond with a CORE_GET_CONFIG_RSP with
933             // a Status field of STATUS_INVALID_PARAM, containing each unavailable
934             // Parameter ID with a Parameter Len field of value zero.
935             nci::CoreGetConfigResponseBuilder {
936                 status: nci::Status::InvalidParam,
937                 parameters: invalid_parameters,
938             }
939         })
940         .await?;
941 
942         Ok(())
943     }
944 
core_conn_create(&mut self, cmd: nci::CoreConnCreateCommand) -> Result<()>945     async fn core_conn_create(&mut self, cmd: nci::CoreConnCreateCommand) -> Result<()> {
946         info!("[{}] CORE_CONN_CREATE_CMD", self.id);
947 
948         let result: std::result::Result<u8, nci::Status> = (|| {
949             // Retrieve an unused connection ID for the logical connection.
950             let conn_id = {
951                 (0..MAX_LOGICAL_CONNECTIONS)
952                     .find(|conn_id| self.state.logical_connections[*conn_id as usize].is_none())
953                     .ok_or(nci::Status::Rejected)?
954             };
955 
956             // Check that the selected destination type is supported and validate
957             // the destination specific parameters.
958             let logical_connection = match cmd.get_destination_type() {
959                 // If the value of Destination Type is that of a Remote NFC
960                 // Endpoint (0x02), then only the Destination-specific Parameter
961                 // with Type 0x00 or proprietary parameters (as defined in Table 16)
962                 // SHALL be present.
963                 nci::DestinationType::RemoteNfcEndpoint => {
964                     let mut rf_discovery_id: Option<u8> = None;
965                     let mut rf_protocol_type: Option<nci::RfProtocolType> = None;
966 
967                     for parameter in cmd.get_parameters() {
968                         match parameter.id {
969                             nci::DestinationSpecificParameterId::RfDiscovery => {
970                                 rf_discovery_id = parameter.value.first().cloned();
971                                 rf_protocol_type = parameter
972                                     .value
973                                     .get(1)
974                                     .and_then(|t| nci::RfProtocolType::try_from(*t).ok());
975                             }
976                             _ => return Err(nci::Status::Rejected),
977                         }
978                     }
979 
980                     LogicalConnection::RemoteNfcEndpoint {
981                         rf_discovery_id: rf_discovery_id.ok_or(nci::Status::Rejected)?,
982                         rf_protocol_type: rf_protocol_type.ok_or(nci::Status::Rejected)?,
983                     }
984                 }
985                 nci::DestinationType::NfccLoopback | nci::DestinationType::Nfcee => {
986                     return Err(nci::Status::Rejected)
987                 }
988             };
989 
990             // The combination of Destination Type and Destination Specific
991             // Parameters SHALL uniquely identify a single destination for the
992             // Logical Connection.
993             if self
994                 .state
995                 .logical_connections
996                 .iter()
997                 .any(|c| c.as_ref() == Some(&logical_connection))
998             {
999                 return Err(nci::Status::Rejected);
1000             }
1001 
1002             // Create the connection.
1003             self.state.logical_connections[conn_id as usize] = Some(logical_connection);
1004 
1005             Ok(conn_id)
1006         })();
1007 
1008         self.send_control(match result {
1009             Ok(conn_id) => nci::CoreConnCreateResponseBuilder {
1010                 status: nci::Status::Ok,
1011                 max_data_packet_payload_size: MAX_DATA_PACKET_PAYLOAD_SIZE,
1012                 initial_number_of_credits: 0xff,
1013                 conn_id: nci::ConnId::from_dynamic(conn_id),
1014             },
1015             Err(status) => nci::CoreConnCreateResponseBuilder {
1016                 status,
1017                 max_data_packet_payload_size: 0,
1018                 initial_number_of_credits: 0xff,
1019                 conn_id: 0.try_into().unwrap(),
1020             },
1021         })
1022         .await?;
1023 
1024         Ok(())
1025     }
1026 
core_conn_close(&mut self, cmd: nci::CoreConnCloseCommand) -> Result<()>1027     async fn core_conn_close(&mut self, cmd: nci::CoreConnCloseCommand) -> Result<()> {
1028         info!("[{}] CORE_CONN_CLOSE_CMD", self.id);
1029 
1030         let conn_id = match cmd.get_conn_id() {
1031             nci::ConnId::StaticRf | nci::ConnId::StaticHci => {
1032                 warn!("[{}] core_conn_close called with static conn_id", self.id);
1033                 self.send_control(nci::CoreConnCloseResponseBuilder {
1034                     status: nci::Status::Rejected,
1035                 })
1036                 .await?;
1037                 return Ok(());
1038             }
1039             nci::ConnId::Dynamic(id) => nci::ConnId::to_dynamic(id),
1040         };
1041 
1042         let status = if conn_id >= MAX_LOGICAL_CONNECTIONS
1043             || self.state.logical_connections[conn_id as usize].is_none()
1044         {
1045             // If there is no connection associated to the Conn ID in the CORE_CONN_CLOSE_CMD, the
1046             // NFCC SHALL reject the connection closure request by sending a CORE_CONN_CLOSE_RSP
1047             // with a Status of STATUS_REJECTED.
1048             nci::Status::Rejected
1049         } else {
1050             // When it receives a CORE_CONN_CLOSE_CMD for an existing connection, the NFCC SHALL
1051             // accept the connection closure request by sending a CORE_CONN_CLOSE_RSP with a Status of
1052             // STATUS_OK, and the Logical Connection is closed.
1053             self.state.logical_connections[conn_id as usize] = None;
1054             nci::Status::Ok
1055         };
1056 
1057         self.send_control(nci::CoreConnCloseResponseBuilder { status }).await?;
1058 
1059         Ok(())
1060     }
1061 
core_set_power_sub_state( &mut self, cmd: nci::CoreSetPowerSubStateCommand, ) -> Result<()>1062     async fn core_set_power_sub_state(
1063         &mut self,
1064         cmd: nci::CoreSetPowerSubStateCommand,
1065     ) -> Result<()> {
1066         info!("[{}] CORE_SET_POWER_SUB_STATE_CMD", self.id);
1067         info!("         State: {:?}", cmd.get_power_state());
1068 
1069         self.send_control(nci::CoreSetPowerSubStateResponseBuilder { status: nci::Status::Ok })
1070             .await?;
1071 
1072         Ok(())
1073     }
1074 
rf_discover_map(&mut self, cmd: nci::RfDiscoverMapCommand) -> Result<()>1075     async fn rf_discover_map(&mut self, cmd: nci::RfDiscoverMapCommand) -> Result<()> {
1076         info!("[{}] RF_DISCOVER_MAP_CMD", self.id);
1077 
1078         self.state.discover_map.clone_from(cmd.get_mapping_configurations());
1079         self.send_control(nci::RfDiscoverMapResponseBuilder { status: nci::Status::Ok }).await?;
1080 
1081         Ok(())
1082     }
1083 
rf_set_listen_mode_routing( &mut self, _cmd: nci::RfSetListenModeRoutingCommand, ) -> Result<()>1084     async fn rf_set_listen_mode_routing(
1085         &mut self,
1086         _cmd: nci::RfSetListenModeRoutingCommand,
1087     ) -> Result<()> {
1088         info!("[{}] RF_SET_LISTEN_MODE_ROUTING_CMD", self.id);
1089 
1090         self.send_control(nci::RfSetListenModeRoutingResponseBuilder { status: nci::Status::Ok })
1091             .await?;
1092 
1093         Ok(())
1094     }
1095 
rf_get_listen_mode_routing( &mut self, _cmd: nci::RfGetListenModeRoutingCommand, ) -> Result<()>1096     async fn rf_get_listen_mode_routing(
1097         &mut self,
1098         _cmd: nci::RfGetListenModeRoutingCommand,
1099     ) -> Result<()> {
1100         info!("[{}] RF_GET_LISTEN_MODE_ROUTING_CMD", self.id);
1101 
1102         self.send_control(nci::RfGetListenModeRoutingResponseBuilder {
1103             status: nci::Status::Ok,
1104             more_to_follow: 0,
1105             routing_entries: vec![],
1106         })
1107         .await?;
1108 
1109         Ok(())
1110     }
1111 
rf_discover(&mut self, cmd: nci::RfDiscoverCommand) -> Result<()>1112     async fn rf_discover(&mut self, cmd: nci::RfDiscoverCommand) -> Result<()> {
1113         info!("[{}] RF_DISCOVER_CMD", self.id);
1114         for config in cmd.get_configurations() {
1115             info!("         TechMode: {:?}", config.technology_and_mode);
1116         }
1117 
1118         if self.state.rf_state != RfState::Idle {
1119             warn!("[{}] rf_discover received in {:?} state", self.id, self.state.rf_state);
1120             self.send_control(nci::RfDiscoverResponseBuilder {
1121                 status: nci::Status::SemanticError,
1122             })
1123             .await?;
1124             return Ok(());
1125         }
1126 
1127         self.state.discover_configuration.clone_from(cmd.get_configurations());
1128         self.state.rf_state = RfState::Discovery;
1129 
1130         self.send_control(nci::RfDiscoverResponseBuilder { status: nci::Status::Ok }).await?;
1131 
1132         Ok(())
1133     }
1134 
rf_discover_select(&mut self, cmd: nci::RfDiscoverSelectCommand) -> Result<()>1135     async fn rf_discover_select(&mut self, cmd: nci::RfDiscoverSelectCommand) -> Result<()> {
1136         info!("[{}] RF_DISCOVER_SELECT_CMD", self.id);
1137         info!("         DiscoveryID: {:?}", cmd.get_rf_discovery_id());
1138         info!("         Protocol: {:?}", cmd.get_rf_protocol());
1139         info!("         Interface: {:?}", cmd.get_rf_interface());
1140 
1141         if self.state.rf_state != RfState::WaitForHostSelect {
1142             warn!("[{}] rf_discover_select received in {:?} state", self.id, self.state.rf_state);
1143             self.send_control(nci::RfDiscoverSelectResponseBuilder {
1144                 status: nci::Status::SemanticError,
1145             })
1146             .await?;
1147             return Ok(());
1148         }
1149 
1150         let rf_discovery_id = match cmd.get_rf_discovery_id() {
1151             nci::RfDiscoveryId::Rfu(_) => {
1152                 warn!("[{}] rf_discover_select with reserved rf_discovery_id", self.id);
1153                 self.send_control(nci::RfDiscoverSelectResponseBuilder {
1154                     status: nci::Status::Rejected,
1155                 })
1156                 .await?;
1157                 return Ok(());
1158             }
1159             nci::RfDiscoveryId::Id(id) => nci::RfDiscoveryId::to_index(id),
1160         };
1161 
1162         // If the RF Discovery ID, RF Protocol or RF Interface is not valid,
1163         // the NFCC SHALL respond with RF_DISCOVER_SELECT_RSP with a Status of
1164         // STATUS_REJECTED.
1165         if rf_discovery_id >= self.state.rf_poll_responses.len() {
1166             warn!("[{}] rf_discover_select with invalid rf_discovery_id", self.id);
1167             self.send_control(nci::RfDiscoverSelectResponseBuilder {
1168                 status: nci::Status::Rejected,
1169             })
1170             .await?;
1171             return Ok(());
1172         }
1173 
1174         if cmd.get_rf_protocol() != self.state.rf_poll_responses[rf_discovery_id].rf_protocol.into()
1175         {
1176             warn!("[{}] rf_discover_select with invalid rf_protocol", self.id);
1177             self.send_control(nci::RfDiscoverSelectResponseBuilder {
1178                 status: nci::Status::Rejected,
1179             })
1180             .await?;
1181             return Ok(());
1182         }
1183 
1184         self.send_control(nci::RfDiscoverSelectResponseBuilder { status: nci::Status::Ok }).await?;
1185 
1186         // Send RF select command to the peer to activate the device.
1187         // The command has varying parameters based on the activated protocol.
1188         self.activate_poll_interface(
1189             rf_discovery_id,
1190             cmd.get_rf_protocol(),
1191             cmd.get_rf_interface(),
1192         )
1193         .await?;
1194 
1195         Ok(())
1196     }
1197 
rf_deactivate(&mut self, cmd: nci::RfDeactivateCommand) -> Result<()>1198     async fn rf_deactivate(&mut self, cmd: nci::RfDeactivateCommand) -> Result<()> {
1199         info!("[{}] RF_DEACTIVATE_CMD", self.id);
1200         info!("         Type: {:?}", cmd.get_deactivation_type());
1201 
1202         use nci::DeactivationType::*;
1203 
1204         let (status, mut next_state) = match (self.state.rf_state, cmd.get_deactivation_type()) {
1205             (RfState::Idle, _) => (nci::Status::SemanticError, RfState::Idle),
1206             (RfState::Discovery, IdleMode) => (nci::Status::Ok, RfState::Idle),
1207             (RfState::Discovery, _) => (nci::Status::SemanticError, RfState::Discovery),
1208             (RfState::PollActive { .. }, IdleMode) => (nci::Status::Ok, RfState::Idle),
1209             (RfState::PollActive { .. }, SleepMode | SleepAfMode) => {
1210                 (nci::Status::Ok, RfState::WaitForHostSelect)
1211             }
1212             (RfState::PollActive { .. }, Discovery) => (nci::Status::Ok, RfState::Discovery),
1213             (RfState::ListenSleep { .. }, IdleMode) => (nci::Status::Ok, RfState::Idle),
1214             (RfState::ListenSleep { .. }, _) => (nci::Status::SemanticError, self.state.rf_state),
1215             (RfState::ListenActive { .. }, IdleMode) => (nci::Status::Ok, RfState::Idle),
1216             (RfState::ListenActive { id, .. }, SleepMode | SleepAfMode) => {
1217                 (nci::Status::Ok, RfState::ListenSleep { id })
1218             }
1219             (RfState::ListenActive { .. }, Discovery) => (nci::Status::Ok, RfState::Discovery),
1220             (RfState::WaitForHostSelect, IdleMode) => (nci::Status::Ok, RfState::Idle),
1221             (RfState::WaitForHostSelect, _) => {
1222                 (nci::Status::SemanticError, RfState::WaitForHostSelect)
1223             }
1224             (RfState::WaitForSelectResponse { .. }, IdleMode) => (nci::Status::Ok, RfState::Idle),
1225             (RfState::WaitForSelectResponse { .. }, _) => {
1226                 (nci::Status::SemanticError, self.state.rf_state)
1227             }
1228         };
1229 
1230         // Update the state now to prevent interface activation from
1231         // completing if a remote device is being selected.
1232         (next_state, self.state.rf_state) = (self.state.rf_state, next_state);
1233 
1234         self.send_control(nci::RfDeactivateResponseBuilder { status }).await?;
1235 
1236         // Deactivate the active RF interface if applicable
1237         // (next_state is the previous state in this context).
1238         match next_state {
1239             RfState::PollActive { .. } | RfState::ListenActive { .. } => {
1240                 info!("[{}] RF_DEACTIVATE_NTF", self.id);
1241                 info!("         Type: {:?}", cmd.get_deactivation_type());
1242                 info!("         Reason: DH_Request");
1243                 self.field_info(rf::FieldStatus::FieldOff, 255).await?;
1244                 self.send_control(nci::RfDeactivateNotificationBuilder {
1245                     deactivation_type: cmd.get_deactivation_type(),
1246                     deactivation_reason: nci::DeactivationReason::DhRequest,
1247                 })
1248                 .await?
1249             }
1250             _ => (),
1251         }
1252 
1253         // Deselect the remote device if applicable.
1254         match next_state {
1255             RfState::PollActive { id, rf_protocol, rf_technology, .. }
1256             | RfState::WaitForSelectResponse { id, rf_protocol, rf_technology, .. } => {
1257                 self.send_rf(rf::DeactivateNotificationBuilder {
1258                     receiver: id,
1259                     protocol: rf_protocol,
1260                     technology: rf_technology,
1261                     bitrate: rf::BitRate::BitRate106KbitS,
1262                     power_level: 255,
1263                     sender: self.id,
1264                     type_: cmd.get_deactivation_type().into(),
1265                     reason: rf::DeactivateReason::EndpointRequest,
1266                 })
1267                 .await?
1268             }
1269             _ => (),
1270         }
1271 
1272         Ok(())
1273     }
1274 
nfcee_discover(&mut self, _cmd: nci::NfceeDiscoverCommand) -> Result<()>1275     async fn nfcee_discover(&mut self, _cmd: nci::NfceeDiscoverCommand) -> Result<()> {
1276         info!("[{}] NFCEE_DISCOVER_CMD", self.id);
1277 
1278         self.send_control(nci::NfceeDiscoverResponseBuilder {
1279             status: nci::Status::Ok,
1280             number_of_nfcees: 1,
1281         })
1282         .await?;
1283 
1284         self.send_control(nci::NfceeDiscoverNotificationBuilder {
1285             nfcee_id: nci::NfceeId::hci_nfcee(0x86),
1286             nfcee_status: nci::NfceeStatus::Disabled,
1287             supported_nfcee_protocols: vec![],
1288             nfcee_information: vec![nci::NfceeInformation {
1289                 r#type: nci::NfceeInformationType::HostId,
1290                 value: vec![0xc0],
1291             }],
1292             nfcee_supply_power: nci::NfceeSupplyPower::NfccHasNoControl,
1293         })
1294         .await?;
1295 
1296         Ok(())
1297     }
1298 
nfcee_mode_set(&mut self, cmd: nci::NfceeModeSetCommand) -> Result<()>1299     async fn nfcee_mode_set(&mut self, cmd: nci::NfceeModeSetCommand) -> Result<()> {
1300         info!("[{}] NFCEE_MODE_SET_CMD", self.id);
1301         info!("         NFCEE ID: {:?}", cmd.get_nfcee_id());
1302         info!("         NFCEE Mode: {:?}", cmd.get_nfcee_mode());
1303 
1304         if cmd.get_nfcee_id() != nci::NfceeId::hci_nfcee(0x86) {
1305             warn!("[{}] nfcee_mode_set with invalid nfcee_id", self.id);
1306             self.send_control(nci::NfceeModeSetResponseBuilder { status: nci::Status::Ok }).await?;
1307             return Ok(());
1308         }
1309 
1310         self.state.nfcee_state = match cmd.get_nfcee_mode() {
1311             nci::NfceeMode::Enable => NfceeState::Enabled,
1312             nci::NfceeMode::Disable => NfceeState::Disabled,
1313         };
1314 
1315         self.send_control(nci::NfceeModeSetResponseBuilder { status: nci::Status::Ok }).await?;
1316 
1317         self.send_control(nci::NfceeModeSetNotificationBuilder { status: nci::Status::Ok }).await?;
1318 
1319         if self.state.nfcee_state == NfceeState::Enabled {
1320             // Android host stack expects this notification to know when the
1321             // NFCEE completes start-up. The list of information entries is
1322             // filled with defaults observed on real phones.
1323             self.send_data(nci::DataPacketBuilder {
1324                 mt: nci::MessageType::Data,
1325                 conn_id: nci::ConnId::StaticHci,
1326                 cr: 0,
1327                 payload: Some(bytes::Bytes::copy_from_slice(&[0x81, 0x43, 0xc0, 0x01])),
1328             })
1329             .await?;
1330 
1331             self.send_control(nci::RfNfceeDiscoveryReqNotificationBuilder {
1332                 information_entries: vec![
1333                     nci::InformationEntry {
1334                         r#type: nci::InformationEntryType::AddDiscoveryRequest,
1335                         nfcee_id: nci::NfceeId::hci_nfcee(0x86),
1336                         rf_technology_and_mode: nci::RfTechnologyAndMode::NfcFPassiveListenMode,
1337                         rf_protocol: nci::RfProtocolType::T3t,
1338                     },
1339                     nci::InformationEntry {
1340                         r#type: nci::InformationEntryType::AddDiscoveryRequest,
1341                         nfcee_id: nci::NfceeId::hci_nfcee(0x86),
1342                         rf_technology_and_mode: nci::RfTechnologyAndMode::NfcAPassiveListenMode,
1343                         rf_protocol: nci::RfProtocolType::IsoDep,
1344                     },
1345                     nci::InformationEntry {
1346                         r#type: nci::InformationEntryType::AddDiscoveryRequest,
1347                         nfcee_id: nci::NfceeId::hci_nfcee(0x86),
1348                         rf_technology_and_mode: nci::RfTechnologyAndMode::NfcBPassiveListenMode,
1349                         rf_protocol: nci::RfProtocolType::IsoDep,
1350                     },
1351                 ],
1352             })
1353             .await?;
1354         }
1355 
1356         Ok(())
1357     }
1358 
android_get_caps(&mut self, _cmd: nci::AndroidGetCapsCommand) -> Result<()>1359     async fn android_get_caps(&mut self, _cmd: nci::AndroidGetCapsCommand) -> Result<()> {
1360         info!("[{}] ANDROID_GET_CAPS_CMD", self.id);
1361         let cap_tlvs = vec![
1362             nci::CapTlv { t: nci::CapTlvType::PassiveObserverMode, v: vec![2] },
1363             nci::CapTlv { t: nci::CapTlvType::PollingFrameNotification, v: vec![1] },
1364             nci::CapTlv { t: nci::CapTlvType::AutotransactPollingLoopFilter, v: vec![1] },
1365             nci::CapTlv {
1366                 t: nci::CapTlvType::NumberOfExitFramesSupported,
1367                 v: vec![NUMBER_OF_SUPPORTED_EXIT_FRAMES],
1368             },
1369         ];
1370         self.send_control(nci::AndroidGetCapsResponseBuilder {
1371             status: nci::Status::Ok,
1372             android_version: 0,
1373             tlvs: cap_tlvs,
1374         })
1375         .await?;
1376         Ok(())
1377     }
1378 
android_passive_observe_mode( &mut self, cmd: nci::AndroidPassiveObserveModeCommand, ) -> Result<()>1379     async fn android_passive_observe_mode(
1380         &mut self,
1381         cmd: nci::AndroidPassiveObserveModeCommand,
1382     ) -> Result<()> {
1383         info!("[{}] ANDROID_PASSIVE_OBSERVE_MODE_CMD", self.id);
1384         info!("     Mode: {:?}", cmd.get_passive_observe_mode());
1385 
1386         self.state.passive_observe_mode =
1387             if cmd.get_passive_observe_mode() == nci::PassiveObserveMode::Disable {
1388                 u8::from(nci::PassiveObserveMode::Disable)
1389             } else {
1390                 u8::from(nci::TechnologyMask::AllOn)
1391             };
1392         self.state.last_observe_mode_state = None;
1393         self.state.exit_frame_start_time = None;
1394         self.send_control(nci::AndroidPassiveObserveModeResponseBuilder {
1395             status: nci::Status::Ok,
1396         })
1397         .await?;
1398         Ok(())
1399     }
1400 
android_set_passive_observer_tech( &mut self, cmd: nci::AndroidSetPassiveObserverTechCommand, ) -> Result<()>1401     async fn android_set_passive_observer_tech(
1402         &mut self,
1403         cmd: nci::AndroidSetPassiveObserverTechCommand,
1404     ) -> Result<()> {
1405         info!("[{}] ANDROID_SET_PASSIVE_OBSERVER_TECH_CMD", self.id);
1406         info!("     Mask: {:#b}", cmd.get_tech_mask());
1407 
1408         self.state.passive_observe_mode = cmd.get_tech_mask();
1409         self.state.last_observe_mode_state = None;
1410         self.state.exit_frame_start_time = None;
1411 
1412         self.send_control(nci::AndroidPassiveObserveModeResponseBuilder {
1413             status: nci::Status::Ok,
1414         })
1415         .await?;
1416         Ok(())
1417     }
1418 
android_query_passive_observe_mode( &mut self, _cmd: nci::AndroidQueryPassiveObserveModeCommand, ) -> Result<()>1419     async fn android_query_passive_observe_mode(
1420         &mut self,
1421         _cmd: nci::AndroidQueryPassiveObserveModeCommand,
1422     ) -> Result<()> {
1423         info!("[{}] ANDROID_QUERY_PASSIVE_OBSERVE_MODE_CMD", self.id);
1424         info!("     Observe mode state: {:#b}", self.state.passive_observe_mode);
1425 
1426         self.send_control(nci::AndroidQueryPassiveObserveModeResponseBuilder {
1427             status: nci::Status::Ok,
1428             passive_observe_mode: self.state.passive_observe_mode,
1429         })
1430         .await?;
1431         Ok(())
1432     }
1433 
android_set_passive_observer_exit_frames( &mut self, cmd: nci::AndroidSetPassiveObserverExitFrameCommand, ) -> Result<()>1434     async fn android_set_passive_observer_exit_frames(
1435         &mut self,
1436         cmd: nci::AndroidSetPassiveObserverExitFrameCommand,
1437     ) -> Result<()> {
1438         info!("[{}] ANDROID_SET_PASSIVE_OBSERVER_EXIT_FRAMES_CMD", self.id);
1439 
1440         if self.state.rf_state == RfState::Idle || self.state.rf_state == RfState::Discovery {
1441             self.state.exit_frames.clear();
1442             self.state.exit_frame_timeout =
1443                 Duration::from_millis(u16::from_le(cmd.get_timeout()) as u64);
1444             let exit_frame_count = cmd.get_exit_frames().len();
1445             info!("number of exit frames {:?}", exit_frame_count);
1446             let incoming_frames = cmd.get_exit_frames();
1447             for frame in incoming_frames.iter() {
1448                 let data_length = frame.field_value[1..].len() / 2;
1449                 let power_states = frame.field_value[0];
1450                 let mut data: Vec<u8> = vec![];
1451                 data.clone_from(&frame.field_value[1..1 + data_length].to_vec());
1452                 let mut mask: Vec<u8> = vec![];
1453                 mask.clone_from(&frame.field_value[1 + data_length..].to_vec());
1454 
1455                 self.state.exit_frames.push(RfExitFrame {
1456                     power_states,
1457                     data,
1458                     mask,
1459                     rf_technology: rf::Technology::from_u8(
1460                         frame.qualifier_type & EXIT_FRAME_QUALIFIER_TECHNOLOGY_MASK,
1461                     ),
1462                     is_prefix_matching_allowed: frame.qualifier_type
1463                         & EXIT_FRAME_QUALIFIER_PREFIX_MATCHING_MASK
1464                         != 0,
1465                 });
1466                 info!("Added exit frame {:?}", self.state.exit_frames.last().unwrap())
1467             }
1468 
1469             self.send_control(nci::AndroidSetPassiveObserverExitFrameResponseBuilder {
1470                 status: nci::Status::Ok,
1471             })
1472             .await?;
1473             return Ok(());
1474         }
1475         self.send_control(nci::AndroidSetPassiveObserverExitFrameResponseBuilder {
1476             status: nci::Status::SemanticError,
1477         })
1478         .await?;
1479         Ok(())
1480     }
1481 
receive_command(&mut self, packet: nci::ControlPacket) -> Result<()>1482     async fn receive_command(&mut self, packet: nci::ControlPacket) -> Result<()> {
1483         use nci::AndroidPacketChild::*;
1484         use nci::ControlPacketChild::*;
1485         use nci::CorePacketChild::*;
1486         use nci::NfceePacketChild::*;
1487         use nci::ProprietaryPacketChild::*;
1488         use nci::RfPacketChild::*;
1489 
1490         match packet.specialize() {
1491             CorePacket(packet) => match packet.specialize() {
1492                 CoreResetCommand(cmd) => self.core_reset(cmd).await,
1493                 CoreInitCommand(cmd) => self.core_init(cmd).await,
1494                 CoreSetConfigCommand(cmd) => self.core_set_config(cmd).await,
1495                 CoreGetConfigCommand(cmd) => self.core_get_config(cmd).await,
1496                 CoreConnCreateCommand(cmd) => self.core_conn_create(cmd).await,
1497                 CoreConnCloseCommand(cmd) => self.core_conn_close(cmd).await,
1498                 CoreSetPowerSubStateCommand(cmd) => self.core_set_power_sub_state(cmd).await,
1499                 _ => unimplemented!("unsupported core oid {:?}", packet.get_oid()),
1500             },
1501             RfPacket(packet) => match packet.specialize() {
1502                 RfDiscoverMapCommand(cmd) => self.rf_discover_map(cmd).await,
1503                 RfSetListenModeRoutingCommand(cmd) => self.rf_set_listen_mode_routing(cmd).await,
1504                 RfGetListenModeRoutingCommand(cmd) => self.rf_get_listen_mode_routing(cmd).await,
1505                 RfDiscoverCommand(cmd) => self.rf_discover(cmd).await,
1506                 RfDiscoverSelectCommand(cmd) => self.rf_discover_select(cmd).await,
1507                 RfDeactivateCommand(cmd) => self.rf_deactivate(cmd).await,
1508                 _ => unimplemented!("unsupported rf oid {:?}", packet.get_oid()),
1509             },
1510             NfceePacket(packet) => match packet.specialize() {
1511                 NfceeDiscoverCommand(cmd) => self.nfcee_discover(cmd).await,
1512                 NfceeModeSetCommand(cmd) => self.nfcee_mode_set(cmd).await,
1513                 _ => unimplemented!("unsupported nfcee oid {:?}", packet.get_oid()),
1514             },
1515             ProprietaryPacket(packet) => match packet.specialize() {
1516                 AndroidPacket(packet) => match packet.specialize() {
1517                     AndroidGetCapsCommand(cmd) => self.android_get_caps(cmd).await,
1518                     AndroidPassiveObserveModeCommand(cmd) => {
1519                         self.android_passive_observe_mode(cmd).await
1520                     }
1521                     AndroidSetPassiveObserverTechCommand(cmd) => {
1522                         self.android_set_passive_observer_tech(cmd).await
1523                     }
1524                     AndroidQueryPassiveObserveModeCommand(cmd) => {
1525                         self.android_query_passive_observe_mode(cmd).await
1526                     }
1527                     AndroidSetPassiveObserverExitFrameCommand(cmd) => {
1528                         self.android_set_passive_observer_exit_frames(cmd).await
1529                     }
1530                     _ => {
1531                         unimplemented!("unsupported android oid {:?}", packet.get_android_sub_oid())
1532                     }
1533                 },
1534                 _ => unimplemented!("unsupported proprietary oid {:?}", packet.get_oid()),
1535             },
1536             _ => unimplemented!("unsupported gid {:?}", packet.get_gid()),
1537         }
1538     }
1539 
rf_conn_data(&mut self, packet: nci::DataPacket) -> Result<()>1540     async fn rf_conn_data(&mut self, packet: nci::DataPacket) -> Result<()> {
1541         info!("[{}] received data on RF logical connection", self.id);
1542 
1543         // TODO(henrichataing) implement credit based control flow.
1544         match self.state.rf_state {
1545             RfState::PollActive {
1546                 id,
1547                 rf_technology,
1548                 rf_protocol: rf::Protocol::IsoDep,
1549                 rf_interface: nci::RfInterfaceType::IsoDep,
1550                 ..
1551             }
1552             | RfState::ListenActive {
1553                 id,
1554                 rf_technology,
1555                 rf_protocol: rf::Protocol::IsoDep,
1556                 rf_interface: nci::RfInterfaceType::IsoDep,
1557                 ..
1558             } => {
1559                 self.send_rf(rf::DataBuilder {
1560                     receiver: id,
1561                     sender: self.id,
1562                     bitrate: rf::BitRate::BitRate106KbitS,
1563                     power_level: 255,
1564                     protocol: rf::Protocol::IsoDep,
1565                     technology: rf_technology,
1566                     data: packet.get_payload().into(),
1567                 })
1568                 .await?;
1569                 // Resplenish the credit count for the RF Connection.
1570                 self.send_control(
1571                     nci::CoreConnCreditsNotificationBuilder {
1572                         connections: vec![nci::ConnectionCredits {
1573                             conn_id: nci::ConnId::StaticRf,
1574                             credits: 1,
1575                         }],
1576                     }
1577                     .build(),
1578                 )
1579                 .await
1580             }
1581             RfState::PollActive {
1582                 rf_protocol: rf::Protocol::IsoDep,
1583                 rf_interface: nci::RfInterfaceType::Frame,
1584                 ..
1585             } => {
1586                 println!("ISO-DEP frame data {:?}", packet.get_payload());
1587                 match packet.get_payload() {
1588                     // RATS command
1589                     // TODO(henrichataing) Send back the response received from
1590                     // the peer in the RF packet.
1591                     [0xe0, _] => {
1592                         warn!("[{}] frame RATS command", self.id);
1593                         self.send_data(nci::DataPacketBuilder {
1594                             mt: nci::MessageType::Data,
1595                             conn_id: nci::ConnId::StaticRf,
1596                             cr: 0,
1597                             payload: Some(bytes::Bytes::copy_from_slice(
1598                                 &self.state.rf_activation_parameters,
1599                             )),
1600                         })
1601                         .await?
1602                     }
1603                     // DESELECT command
1604                     // TODO(henrichataing) check if the command should be
1605                     // forwarded to the peer, and if it warrants a response
1606                     [0xc2] => warn!("[{}] unimplemented frame DESELECT command", self.id),
1607                     // SLP_REQ command
1608                     // No response is expected for this command.
1609                     // TODO(henrichataing) forward a deactivation request to
1610                     // the peer and deactivate the local interface.
1611                     [0x50, 0x00] => warn!("[{}] unimplemented frame SLP_REQ command", self.id),
1612                     _ => unimplemented!(),
1613                 };
1614                 // Resplenish the credit count for the RF Connection.
1615                 self.send_control(
1616                     nci::CoreConnCreditsNotificationBuilder {
1617                         connections: vec![nci::ConnectionCredits {
1618                             conn_id: nci::ConnId::StaticRf,
1619                             credits: 1,
1620                         }],
1621                     }
1622                     .build(),
1623                 )
1624                 .await
1625             }
1626             RfState::PollActive { rf_protocol, rf_interface, .. }
1627             | RfState::ListenActive { rf_protocol, rf_interface, .. } => unimplemented!(
1628                 "unsupported combination of RF protocol {:?} and interface {:?}",
1629                 rf_protocol,
1630                 rf_interface
1631             ),
1632             _ => {
1633                 warn!(
1634                     "[{}] ignored RF data packet while not in active listen or poll mode",
1635                     self.id
1636                 );
1637                 Ok(())
1638             }
1639         }
1640     }
1641 
hci_conn_data(&mut self, _packet: nci::DataPacket) -> Result<()>1642     async fn hci_conn_data(&mut self, _packet: nci::DataPacket) -> Result<()> {
1643         info!("[{}] received data on HCI logical connection", self.id);
1644         Ok(())
1645     }
1646 
dynamic_conn_data(&mut self, conn_id: u8, packet: nci::DataPacket) -> Result<()>1647     async fn dynamic_conn_data(&mut self, conn_id: u8, packet: nci::DataPacket) -> Result<()> {
1648         info!("[{}] received data on dynamic logical connection", self.id);
1649         let response = packet.get_payload();
1650 
1651         self.send_data(nci::DataPacketBuilder {
1652             mt: nci::MessageType::Data,
1653             conn_id: nci::ConnId::from_dynamic(conn_id),
1654             cr: 0,
1655             payload: Some(bytes::Bytes::copy_from_slice(response)),
1656         })
1657         .await?;
1658 
1659         // Resplenish the credit count for the HCI Connection.
1660         self.send_control(
1661             nci::CoreConnCreditsNotificationBuilder {
1662                 connections: vec![nci::ConnectionCredits {
1663                     conn_id: nci::ConnId::from_dynamic(conn_id),
1664                     credits: 1,
1665                 }],
1666             }
1667             .build(),
1668         )
1669         .await
1670     }
1671 
receive_data(&mut self, packet: nci::DataPacket) -> Result<()>1672     async fn receive_data(&mut self, packet: nci::DataPacket) -> Result<()> {
1673         info!("[{}] receive_data({})", self.id, u8::from(packet.get_conn_id()));
1674 
1675         match packet.get_conn_id() {
1676             nci::ConnId::StaticRf => self.rf_conn_data(packet).await,
1677             nci::ConnId::StaticHci => self.hci_conn_data(packet).await,
1678             nci::ConnId::Dynamic(id) => self.dynamic_conn_data(*id, packet).await,
1679         }
1680     }
1681 
field_info(&mut self, field_status: rf::FieldStatus, power_level: u8) -> Result<()>1682     async fn field_info(&mut self, field_status: rf::FieldStatus, power_level: u8) -> Result<()> {
1683         if self.state.remote_field_status != field_status {
1684             if self.state.config_parameters.rf_field_info != 0 {
1685                 self.send_control(nci::RfFieldInfoNotificationBuilder {
1686                     rf_field_status: match field_status {
1687                         rf::FieldStatus::FieldOn => nci::RfFieldStatus::FieldDetected,
1688                         rf::FieldStatus::FieldOff => nci::RfFieldStatus::NoFieldDetected,
1689                     },
1690                 })
1691                 .await?;
1692             }
1693             self.send_control(nci::AndroidPollingLoopNotificationBuilder {
1694                 polling_frames: vec![nci::PollingFrame {
1695                     frame_type: nci::PollingFrameType::RemoteField,
1696                     flags: nci::PollingFrameFlags { format: nci::PollingFrameFormat::Short },
1697                     timestamp: (self.state.start_time.elapsed().as_micros() as u32).to_be_bytes(),
1698                     gain: power_level,
1699                     payload: vec![field_status.into()],
1700                 }],
1701             })
1702             .await?;
1703             self.state.remote_field_status = field_status;
1704         }
1705         Ok(())
1706     }
1707 
poll_command(&mut self, cmd: rf::PollCommand) -> Result<()>1708     async fn poll_command(&mut self, cmd: rf::PollCommand) -> Result<()> {
1709         trace!("[{}] poll_command()", self.id);
1710 
1711         if self.state.rf_state != RfState::Discovery {
1712             return Ok(());
1713         }
1714         let technology = cmd.get_technology();
1715 
1716         // Android proprietary extension for polling frame notifications.
1717         // The NFCC should send the NCI_ANDROID_POLLING_FRAME_NTF to the Host
1718         // after each polling loop frame
1719         // This notification is independent of whether Passive Observe Mode is
1720         // active or not. When Passive Observe Mode is active, the NFCC
1721         // should always send this notification before proceeding with the
1722         // transaction.
1723 
1724         let data = cmd.get_payload();
1725         let format = cmd.get_format();
1726 
1727         let (crc_valid, data) = match technology {
1728             // If frame longer than 2 bytes has valid CRC
1729             // cut it (2 last bytes) out of result
1730             rf::Technology::NfcA | rf::Technology::NfcB
1731                 if data.len() > 2
1732                     && format == rf::PollingFrameFormat::Long
1733                     && crc::verify_crc(technology, data).is_ok() =>
1734             {
1735                 (true, data[0..data.len() - 2].to_vec())
1736             }
1737             // If length of data is less than 2 bytes,
1738             // or the last byte does not contain 8 bits, there can be no CRC
1739             // Frames without or with invalid CRC are returned in full
1740             _ => (false, data.to_vec()),
1741         };
1742 
1743         if self.has_exit_frame(&data, technology) {
1744             self.state.last_observe_mode_state = Some(self.state.passive_observe_mode);
1745             self.state.passive_observe_mode = nci::PassiveObserveMode::Disable.into();
1746             self.state.exit_frame_start_time = Some(Instant::now());
1747 
1748             self.send_control(nci::PassiveObserverSuspendedNotificationBuilder {
1749                 exit_frame_type: match technology {
1750                     rf::Technology::NfcA => 0x00,
1751                     rf::Technology::NfcB => 0x01,
1752                     _ => panic!(),
1753                 },
1754                 payload: Some(data.clone().into()),
1755             })
1756             .await?;
1757         }
1758 
1759         self.send_control(nci::AndroidPollingLoopNotificationBuilder {
1760             polling_frames: vec![nci::PollingFrame {
1761                 frame_type: match technology {
1762                     rf::Technology::NfcA => {
1763                         // WUPA/REQA
1764                         // Musn't have CRC
1765                         if !crc_valid
1766                             // have short format (7 bits in last byte)
1767                             && format == rf::PollingFrameFormat::Short
1768                             // 1 byte long in total
1769                             && data.len() == 1
1770                             // start with 0x52 (WUPA) or 0x26 (REQA)
1771                             && (data[0] == 0x52 || data[0] == 0x26)
1772                         {
1773                             nci::PollingFrameType::Reqa
1774                         } else {
1775                             // Other are considered as polling loop annotations
1776                             nci::PollingFrameType::Unknown
1777                         }
1778                     }
1779                     rf::Technology::NfcB => {
1780                         // REQB/WUPB
1781                         // Must have valid CRC
1782                         if crc_valid
1783                             // have long format (8 bits in last byte)
1784                             && format == rf::PollingFrameFormat::Long
1785                             // 3 bytes long (APf, AFI and PARAM)
1786                             && data.len() == 3
1787                             // start with 0x05 (APf)
1788                             && data[0] == 0x05
1789                         {
1790                             nci::PollingFrameType::Reqb
1791                         } else {
1792                             // Other are considered as polling loop annotations
1793                             nci::PollingFrameType::Unknown
1794                         }
1795                     }
1796                     // Type F frames cannot serve as polling loop annotations
1797                     rf::Technology::NfcF => nci::PollingFrameType::Reqf,
1798                     // Type V frames cannot serve as polling loop annotations
1799                     rf::Technology::NfcV => nci::PollingFrameType::Reqv,
1800                     rf::Technology::Raw => nci::PollingFrameType::Unknown,
1801                 },
1802                 // NCI_ANDROID_POLLING_FRAME_NTF Flags
1803                 // b0: 0 - short frame; 1 - long frame
1804                 flags: nci::PollingFrameFlags {
1805                     format: match format {
1806                         rf::PollingFrameFormat::Long => nci::PollingFrameFormat::Long,
1807                         rf::PollingFrameFormat::Short => nci::PollingFrameFormat::Short,
1808                     },
1809                 },
1810                 timestamp: (self.state.start_time.elapsed().as_micros() as u32).to_be_bytes(),
1811                 gain: cmd.get_power_level(),
1812                 payload: data,
1813             }],
1814         })
1815         .await?;
1816 
1817         // When the Passive Observe Mode is active, the NFCC shall not respond
1818         // to any poll requests during the polling loop in Listen Mode, until
1819         // explicitly authorized by the Host.
1820         let mask: u8 = match technology {
1821             rf::Technology::NfcA => nci::TechnologyMask::NfcA.into(),
1822             rf::Technology::NfcB => nci::TechnologyMask::NfcB.into(),
1823             rf::Technology::NfcF => nci::TechnologyMask::NfcF.into(),
1824             rf::Technology::NfcV => nci::TechnologyMask::NfcV.into(),
1825             _ => 0,
1826         };
1827         if self.state.passive_observe_mode & mask != 0 {
1828             return Ok(());
1829         }
1830 
1831         if self.state.discover_configuration.iter().any(|config| {
1832             matches!(
1833                 (config.technology_and_mode, technology),
1834                 (nci::RfTechnologyAndMode::NfcAPassiveListenMode, rf::Technology::NfcA)
1835                     | (nci::RfTechnologyAndMode::NfcBPassiveListenMode, rf::Technology::NfcB)
1836                     | (nci::RfTechnologyAndMode::NfcFPassiveListenMode, rf::Technology::NfcF)
1837             )
1838         }) {
1839             match technology {
1840                 rf::Technology::NfcA => {
1841                     self.send_rf(rf::NfcAPollResponseBuilder {
1842                         protocol: rf::Protocol::Undetermined,
1843                         receiver: cmd.get_sender(),
1844                         sender: self.id,
1845                         bitrate: rf::BitRate::BitRate106KbitS,
1846                         power_level: 255,
1847                         nfcid1: self.state.nfcid1(),
1848                         int_protocol: self.state.config_parameters.la_sel_info >> 5,
1849                         bit_frame_sdd: self.state.config_parameters.la_bit_frame_sdd,
1850                     })
1851                     .await?
1852                 }
1853                 // TODO(b/346715736) implement support for NFC-B technology
1854                 rf::Technology::NfcB => (),
1855                 rf::Technology::NfcF => (),
1856                 _ => (),
1857             }
1858         }
1859 
1860         Ok(())
1861     }
1862 
has_exit_frame(&mut self, polling_frame_data: &[u8], rf_technology: rf::Technology) -> bool1863     fn has_exit_frame(&mut self, polling_frame_data: &[u8], rf_technology: rf::Technology) -> bool {
1864         'frame_loop: for exit_frame in self.state.exit_frames.iter() {
1865             if rf_technology != exit_frame.rf_technology {
1866                 continue;
1867             }
1868 
1869             let exit_frame_len = exit_frame.data.len();
1870             // This checks if the data in the exit frame matches the polling frame.
1871             for n in 0..exit_frame_len {
1872                 if n >= polling_frame_data.len()
1873                     || exit_frame.data[n] != (polling_frame_data[n] & exit_frame.mask[n])
1874                 {
1875                     continue 'frame_loop;
1876                 }
1877             }
1878             // TODO(johnrjohn) Check if power state matches.
1879 
1880             // If the lengths do not match, or if prefix matching is not allowed, it means there
1881             // is unmatched data in the polling frame and this isn't a match.
1882             if exit_frame.data.len() == polling_frame_data.len()
1883                 || exit_frame.is_prefix_matching_allowed
1884             {
1885                 info!(
1886                     "Exit frame matched! PollingFrame: {:?}, ExitFrame {:?}",
1887                     polling_frame_data, exit_frame
1888                 );
1889                 return true;
1890             }
1891         }
1892         false
1893     }
1894 
nfca_poll_response(&mut self, cmd: rf::NfcAPollResponse) -> Result<()>1895     async fn nfca_poll_response(&mut self, cmd: rf::NfcAPollResponse) -> Result<()> {
1896         info!("[{}] nfca_poll_response()", self.id);
1897 
1898         if self.state.rf_state != RfState::Discovery {
1899             return Ok(());
1900         }
1901 
1902         let int_protocol = cmd.get_int_protocol();
1903         let rf_protocols = match int_protocol {
1904             0b00 => [rf::Protocol::T2t].iter(),
1905             0b01 => [rf::Protocol::IsoDep].iter(),
1906             0b10 => [rf::Protocol::NfcDep].iter(),
1907             0b11 => [rf::Protocol::NfcDep, rf::Protocol::IsoDep].iter(),
1908             _ => return Ok(()),
1909         };
1910         let sens_res = match cmd.get_nfcid1().len() {
1911             4 => 0x00,
1912             7 => 0x40,
1913             10 => 0x80,
1914             _ => panic!(),
1915         } | cmd.get_bit_frame_sdd() as u16;
1916         let sel_res = int_protocol << 5;
1917 
1918         for rf_protocol in rf_protocols {
1919             self.state.add_poll_response(RfPollResponse {
1920                 id: cmd.get_sender(),
1921                 rf_protocol: *rf_protocol,
1922                 rf_technology: rf::Technology::NfcA,
1923                 rf_technology_specific_parameters:
1924                     nci::NfcAPollModeTechnologySpecificParametersBuilder {
1925                         sens_res,
1926                         nfcid1: cmd.get_nfcid1().clone(),
1927                         sel_res,
1928                     }
1929                     .build()
1930                     .encode_to_vec()?,
1931             })
1932         }
1933 
1934         Ok(())
1935     }
1936 
t4at_select_command(&mut self, cmd: rf::T4ATSelectCommand) -> Result<()>1937     async fn t4at_select_command(&mut self, cmd: rf::T4ATSelectCommand) -> Result<()> {
1938         info!("[{}] t4at_select_command()", self.id);
1939 
1940         match self.state.rf_state {
1941             RfState::Discovery => (),
1942             RfState::ListenSleep { id } if id == cmd.get_sender() => (),
1943             _ => return Ok(()),
1944         };
1945 
1946         // TODO(henrichataing): validate that the protocol and technology are
1947         // valid for the current discovery settings.
1948 
1949         // TODO(henrichataing): use listen mode routing table to decide which
1950         // interface should be used for the activating device.
1951 
1952         self.state.rf_state = RfState::ListenActive {
1953             id: cmd.get_sender(),
1954             rf_technology: rf::Technology::NfcA,
1955             rf_protocol: rf::Protocol::IsoDep,
1956             rf_interface: nci::RfInterfaceType::IsoDep,
1957         };
1958 
1959         // [DIGITAL] 14.6.2 RATS Response (Answer To Select)
1960         // Construct the response from the values passed in the configuration
1961         // parameters. The TL byte is excluded from the response.
1962         let mut rats_response = vec![
1963             0x78, // TC(1), TB(1), TA(1) transmitted, FSCI=8
1964             0x80, // TA(1)
1965             self.state.config_parameters.li_a_rats_tb1,
1966             self.state.config_parameters.li_a_rats_tc1,
1967         ];
1968 
1969         rats_response.extend_from_slice(&self.state.config_parameters.li_a_hist_by);
1970 
1971         self.send_rf(rf::T4ATSelectResponseBuilder {
1972             receiver: cmd.get_sender(),
1973             sender: self.id,
1974             bitrate: rf::BitRate::BitRate106KbitS,
1975             power_level: 255,
1976             rats_response,
1977         })
1978         .await?;
1979 
1980         info!("[{}] RF_INTF_ACTIVATED_NTF", self.id);
1981         info!("         DiscoveryID: {:?}", nci::RfDiscoveryId::from_index(0));
1982         info!("         Interface: ISO-DEP");
1983         info!("         Protocol: ISO-DEP");
1984         info!("         ActivationTechnology: NFC_A_PASSIVE_LISTEN");
1985         info!("         RATS: {}", cmd.get_param());
1986 
1987         self.send_control(nci::RfIntfActivatedNotificationBuilder {
1988             rf_discovery_id: nci::RfDiscoveryId::from_index(0),
1989             rf_interface: nci::RfInterfaceType::IsoDep,
1990             rf_protocol: nci::RfProtocolType::IsoDep,
1991             activation_rf_technology_and_mode: nci::RfTechnologyAndMode::NfcAPassiveListenMode,
1992             max_data_packet_payload_size: MAX_DATA_PACKET_PAYLOAD_SIZE,
1993             initial_number_of_credits: 1,
1994             // No parameters are currently defined for NFC-A Listen Mode.
1995             rf_technology_specific_parameters: vec![],
1996             data_exchange_rf_technology_and_mode: nci::RfTechnologyAndMode::NfcAPassiveListenMode,
1997             data_exchange_transmit_bit_rate: nci::BitRate::BitRate106KbitS,
1998             data_exchange_receive_bit_rate: nci::BitRate::BitRate106KbitS,
1999             activation_parameters: nci::NfcAIsoDepListenModeActivationParametersBuilder {
2000                 param: cmd.get_param(),
2001             }
2002             .build()
2003             .encode_to_vec()?,
2004         })
2005         .await?;
2006 
2007         Ok(())
2008     }
2009 
t4at_select_response(&mut self, cmd: rf::T4ATSelectResponse) -> Result<()>2010     async fn t4at_select_response(&mut self, cmd: rf::T4ATSelectResponse) -> Result<()> {
2011         info!("[{}] t4at_select_response()", self.id);
2012 
2013         let (id, rf_discovery_id, rf_interface, rf_protocol) = match self.state.rf_state {
2014             RfState::WaitForSelectResponse {
2015                 id,
2016                 rf_discovery_id,
2017                 rf_interface,
2018                 rf_protocol,
2019                 ..
2020             } => (id, rf_discovery_id, rf_interface, rf_protocol),
2021             _ => return Ok(()),
2022         };
2023 
2024         if cmd.get_sender() != id {
2025             return Ok(());
2026         }
2027 
2028         self.state.rf_state = RfState::PollActive {
2029             id,
2030             rf_protocol: self.state.rf_poll_responses[rf_discovery_id].rf_protocol,
2031             rf_technology: self.state.rf_poll_responses[rf_discovery_id].rf_technology,
2032             rf_interface,
2033         };
2034 
2035         // Save the activation parameters for the RF frame interface
2036         // implementation. Note: TL is not included in the RATS response
2037         // and needs to be added manually to the activation parameters.
2038         self.state.rf_activation_parameters = vec![cmd.get_rats_response().len() as u8];
2039         self.state.rf_activation_parameters.extend_from_slice(cmd.get_rats_response());
2040 
2041         info!("[{}] RF_INTF_ACTIVATED_NTF", self.id);
2042         info!("         DiscoveryID: {:?}", nci::RfDiscoveryId::from_index(rf_discovery_id));
2043         info!("         Interface: {:?}", rf_interface);
2044         info!("         Protocol: {:?}", rf_protocol);
2045         info!("         ActivationTechnology: NFC_A_PASSIVE_POLL");
2046         info!("         RATS: {:?}", cmd.get_rats_response());
2047 
2048         self.send_control(nci::RfIntfActivatedNotificationBuilder {
2049             rf_discovery_id: nci::RfDiscoveryId::from_index(rf_discovery_id),
2050             rf_interface,
2051             rf_protocol: rf_protocol.into(),
2052             activation_rf_technology_and_mode: nci::RfTechnologyAndMode::NfcAPassivePollMode,
2053             max_data_packet_payload_size: MAX_DATA_PACKET_PAYLOAD_SIZE,
2054             initial_number_of_credits: 1,
2055             rf_technology_specific_parameters: self.state.rf_poll_responses[rf_discovery_id]
2056                 .rf_technology_specific_parameters
2057                 .clone(),
2058             data_exchange_rf_technology_and_mode: nci::RfTechnologyAndMode::NfcAPassivePollMode,
2059             data_exchange_transmit_bit_rate: nci::BitRate::BitRate106KbitS,
2060             data_exchange_receive_bit_rate: nci::BitRate::BitRate106KbitS,
2061             // TODO(hchataing) the activation parameters should be empty
2062             // when the RF frame interface is used, since the protocol
2063             // activation is managed by the DH.
2064             activation_parameters: nci::NfcAIsoDepPollModeActivationParametersBuilder {
2065                 rats_response: cmd.get_rats_response().clone(),
2066             }
2067             .build()
2068             .encode_to_vec()?,
2069         })
2070         .await?;
2071 
2072         Ok(())
2073     }
2074 
data_packet(&mut self, data: rf::Data) -> Result<()>2075     async fn data_packet(&mut self, data: rf::Data) -> Result<()> {
2076         info!("[{}] data_packet()", self.id);
2077 
2078         match (self.state.rf_state, data.get_protocol()) {
2079             (
2080                 RfState::PollActive {
2081                     id, rf_technology, rf_protocol: rf::Protocol::IsoDep, ..
2082                 },
2083                 rf::Protocol::IsoDep,
2084             )
2085             | (
2086                 RfState::ListenActive {
2087                     id, rf_technology, rf_protocol: rf::Protocol::IsoDep, ..
2088                 },
2089                 rf::Protocol::IsoDep,
2090             ) if data.get_sender() == id && data.get_technology() == rf_technology => {
2091                 self.send_data(nci::DataPacketBuilder {
2092                     mt: nci::MessageType::Data,
2093                     conn_id: nci::ConnId::StaticRf,
2094                     cr: 1, // TODO(henrichataing): credit based control flow
2095                     payload: Some(bytes::Bytes::copy_from_slice(data.get_data())),
2096                 })
2097                 .await
2098             }
2099             (RfState::PollActive { id, .. }, _) | (RfState::ListenActive { id, .. }, _)
2100                 if id != data.get_sender() =>
2101             {
2102                 warn!("[{}] ignored RF data packet sent from an un-selected device", self.id);
2103                 Ok(())
2104             }
2105             (RfState::PollActive { .. }, _) | (RfState::ListenActive { .. }, _) => {
2106                 unimplemented!("unsupported combination of technology and protocol")
2107             }
2108             (_, _) => {
2109                 warn!("[{}] ignored RF data packet received in inactive state", self.id);
2110                 Ok(())
2111             }
2112         }
2113     }
2114 
deactivate_notification(&mut self, cmd: rf::DeactivateNotification) -> Result<()>2115     async fn deactivate_notification(&mut self, cmd: rf::DeactivateNotification) -> Result<()> {
2116         info!("[{}] deactivate_notification()", self.id);
2117 
2118         use rf::DeactivateType::*;
2119 
2120         let mut next_state = match (self.state.rf_state, cmd.get_type_()) {
2121             (RfState::PollActive { id, .. }, IdleMode) if id == cmd.get_sender() => RfState::Idle,
2122             (RfState::PollActive { id, .. }, SleepMode | SleepAfMode) if id == cmd.get_sender() => {
2123                 RfState::WaitForHostSelect
2124             }
2125             (RfState::PollActive { id, .. }, Discovery) if id == cmd.get_sender() => {
2126                 RfState::Discovery
2127             }
2128             (RfState::ListenSleep { id, .. }, IdleMode) if id == cmd.get_sender() => RfState::Idle,
2129             (RfState::ListenSleep { id, .. }, Discovery) if id == cmd.get_sender() => {
2130                 RfState::Discovery
2131             }
2132             (RfState::ListenActive { id, .. }, IdleMode) if id == cmd.get_sender() => RfState::Idle,
2133             (RfState::ListenActive { id, .. }, SleepMode | SleepAfMode)
2134                 if id == cmd.get_sender() =>
2135             {
2136                 RfState::ListenSleep { id }
2137             }
2138             (RfState::ListenActive { id, .. }, Discovery) if id == cmd.get_sender() => {
2139                 RfState::Discovery
2140             }
2141             (_, _) => self.state.rf_state,
2142         };
2143 
2144         // Update the state now to prevent interface activation from
2145         // completing if a remote device is being selected.
2146         (next_state, self.state.rf_state) = (self.state.rf_state, next_state);
2147 
2148         // Deactivate the active RF interface if applicable.
2149         if next_state != self.state.rf_state {
2150             self.field_info(rf::FieldStatus::FieldOff, 255).await?;
2151             self.send_control(nci::RfDeactivateNotificationBuilder {
2152                 deactivation_type: cmd.get_type_().into(),
2153                 deactivation_reason: cmd.get_reason().into(),
2154             })
2155             .await?
2156         }
2157 
2158         Ok(())
2159     }
2160 
receive_rf(&mut self, packet: rf::RfPacket) -> Result<()>2161     async fn receive_rf(&mut self, packet: rf::RfPacket) -> Result<()> {
2162         use rf::RfPacketChild::*;
2163 
2164         match packet.specialize() {
2165             PollCommand(cmd) => self.poll_command(cmd).await,
2166             FieldInfo(cmd) => self.field_info(cmd.get_field_status(), cmd.get_power_level()).await,
2167             NfcAPollResponse(cmd) => self.nfca_poll_response(cmd).await,
2168             // [NCI] 5.2.2 State RFST_DISCOVERY
2169             // If discovered by a Remote NFC Endpoint in Listen mode, once the
2170             // Remote NFC Endpoint has established any underlying protocol(s) needed
2171             // by the configured RF Interface, the NFCC SHALL send
2172             // RF_INTF_ACTIVATED_NTF (Listen Mode) to the DH and the state is
2173             // changed to RFST_LISTEN_ACTIVE.
2174             T4ATSelectCommand(cmd) => self.t4at_select_command(cmd).await,
2175             T4ATSelectResponse(cmd) => self.t4at_select_response(cmd).await,
2176             SelectCommand(_) => unimplemented!(),
2177             DeactivateNotification(cmd) => self.deactivate_notification(cmd).await,
2178             Data(cmd) => self.data_packet(cmd).await,
2179             _ => unimplemented!(),
2180         }
2181     }
2182 
2183     /// Activity for activating an RF interface for a discovered device.
2184     ///
2185     /// The method send a notification when the interface is successfully
2186     /// activated, or when the device activation fails.
2187     ///
2188     ///  * `rf_discovery_id` - index of the discovered device
2189     ///  * `rf_interface` - interface to activate
2190     ///
2191     /// The RF state is changed to WaitForSelectResponse when
2192     /// the select command is successfully sent.
activate_poll_interface( &mut self, rf_discovery_id: usize, rf_protocol: nci::RfProtocolType, rf_interface: nci::RfInterfaceType, ) -> Result<()>2193     async fn activate_poll_interface(
2194         &mut self,
2195         rf_discovery_id: usize,
2196         rf_protocol: nci::RfProtocolType,
2197         rf_interface: nci::RfInterfaceType,
2198     ) -> Result<()> {
2199         info!("[{}] activate_poll_interface({:?})", self.id, rf_interface);
2200 
2201         let rf_technology = self.state.rf_poll_responses[rf_discovery_id].rf_technology;
2202         match (rf_protocol, rf_technology) {
2203             (nci::RfProtocolType::T2t, rf::Technology::NfcA) => {
2204                 self.send_rf(rf::SelectCommandBuilder {
2205                     sender: self.id,
2206                     receiver: self.state.rf_poll_responses[rf_discovery_id].id,
2207                     technology: rf::Technology::NfcA,
2208                     bitrate: rf::BitRate::BitRate106KbitS,
2209                     power_level: 255,
2210                     protocol: rf::Protocol::T2t,
2211                 })
2212                 .await?
2213             }
2214             (nci::RfProtocolType::IsoDep, rf::Technology::NfcA) => {
2215                 self.send_rf(rf::T4ATSelectCommandBuilder {
2216                     sender: self.id,
2217                     receiver: self.state.rf_poll_responses[rf_discovery_id].id,
2218                     bitrate: rf::BitRate::BitRate106KbitS,
2219                     power_level: 255,
2220                     // [DIGITAL] 14.6.1.6 The FSD supported by the
2221                     // Reader/Writer SHALL be FSD T4AT,MIN
2222                     // (set to 256 in Appendix B.6).
2223                     param: 0x80,
2224                 })
2225                 .await?
2226             }
2227             (nci::RfProtocolType::NfcDep, rf::Technology::NfcA) => {
2228                 self.send_rf(rf::NfcDepSelectCommandBuilder {
2229                     sender: self.id,
2230                     receiver: self.state.rf_poll_responses[rf_discovery_id].id,
2231                     bitrate: rf::BitRate::BitRate106KbitS,
2232                     power_level: 255,
2233                     technology: rf::Technology::NfcA,
2234                     lr: 0,
2235                 })
2236                 .await?
2237             }
2238             _ => todo!(),
2239         }
2240 
2241         self.state.rf_state = RfState::WaitForSelectResponse {
2242             id: self.state.rf_poll_responses[rf_discovery_id].id,
2243             rf_discovery_id,
2244             rf_interface,
2245             rf_protocol: rf_protocol.into(),
2246             rf_technology,
2247         };
2248         Ok(())
2249     }
2250 
run_until<O>(&mut self, future: impl Future<Output = O>) -> Result<O>2251     async fn run_until<O>(&mut self, future: impl Future<Output = O>) -> Result<O> {
2252         let mut future = pin!(future);
2253         loop {
2254             tokio::select! {
2255                 packet = self.nci_stream.next() => {
2256                     let packet = packet.ok_or(anyhow::anyhow!("nci channel closed"))??;
2257                     let header = nci::PacketHeader::parse(&packet[0..3])?;
2258                     match header.get_mt() {
2259                         nci::MessageType::Data => {
2260                             self.receive_data(nci::DataPacket::parse(&packet)?).await?
2261                         }
2262                         nci::MessageType::Command => {
2263                             self.receive_command(nci::ControlPacket::parse(&packet)?).await?
2264                         }
2265                         mt => {
2266                             return Err(anyhow::anyhow!(
2267                                 "unexpected message type {:?} in received NCI packet",
2268                                 mt
2269                             ))
2270                         }
2271                     }
2272                 },
2273                 rf_packet = self.rf_rx.recv() => {
2274                     self.receive_rf(
2275                         rf_packet.ok_or(anyhow::anyhow!("rf_rx channel closed"))?,
2276                     )
2277                     .await?
2278                 },
2279                 output = &mut future => break Ok(output)
2280             }
2281         }
2282     }
2283 
2284     /// Timer handler method. This function is invoked at regular interval
2285     /// on the NFCC instance and is used to drive internal timers.
tick(&mut self) -> Result<()>2286     async fn tick(&mut self) -> Result<()> {
2287         if self.state.rf_state != RfState::Discovery {
2288             return Ok(());
2289         }
2290 
2291         if self.state.exit_frame_start_time.is_some() {
2292             let elapsed_ms = self.state.exit_frame_start_time.unwrap().elapsed().as_millis();
2293             if elapsed_ms > self.state.exit_frame_timeout.as_millis() {
2294                 self.state.exit_frame_start_time = None;
2295                 self.state.passive_observe_mode =
2296                     self.state.last_observe_mode_state.unwrap_or(nci::TechnologyMask::AllOn.into());
2297                 info!("Turning observe mode back on, exit frame timeout has passed.");
2298                 self.send_control(nci::PassiveObserverResumedNotificationBuilder {}).await?;
2299             }
2300         }
2301 
2302         //info!("[{}] poll", self.id);
2303 
2304         // [NCI] 5.2.2 State RFST_DISCOVERY
2305         //
2306         // In this state the NFCC stays in Poll Mode and/or Listen Mode (based
2307         // on the discovery configuration) until at least one Remote NFC
2308         // Endpoint is detected or the RF Discovery Process is stopped by
2309         // the DH.
2310         //
2311         // The following implements the Poll Mode Discovery, Listen Mode
2312         // Discover is implicitly implemented in response to poll and
2313         // select commands.
2314 
2315         // RF Discovery is ongoing and no peer device has been discovered
2316         // so far. Send a RF poll command for all enabled technologies.
2317         self.state.rf_poll_responses.clear();
2318         for configuration in self.state.discover_configuration.iter() {
2319             self.send_rf(rf::PollCommandBuilder {
2320                 sender: self.id,
2321                 receiver: u16::MAX,
2322                 protocol: rf::Protocol::Undetermined,
2323                 technology: match configuration.technology_and_mode {
2324                     nci::RfTechnologyAndMode::NfcAPassivePollMode => rf::Technology::NfcA,
2325                     nci::RfTechnologyAndMode::NfcBPassivePollMode => rf::Technology::NfcB,
2326                     nci::RfTechnologyAndMode::NfcFPassivePollMode => rf::Technology::NfcF,
2327                     nci::RfTechnologyAndMode::NfcVPassivePollMode => rf::Technology::NfcV,
2328                     _ => continue,
2329                 },
2330                 format: match configuration.technology_and_mode {
2331                     nci::RfTechnologyAndMode::NfcAPassivePollMode => rf::PollingFrameFormat::Short,
2332                     _ => rf::PollingFrameFormat::Long,
2333                 },
2334                 bitrate: match configuration.technology_and_mode {
2335                     nci::RfTechnologyAndMode::NfcFPassivePollMode => rf::BitRate::BitRate212KbitS,
2336                     nci::RfTechnologyAndMode::NfcVPassivePollMode => rf::BitRate::BitRate26KbitS,
2337                     _ => rf::BitRate::BitRate106KbitS,
2338                 },
2339                 power_level: 255,
2340                 payload: Some(bytes::Bytes::new()),
2341             })
2342             .await?
2343         }
2344 
2345         // Wait for poll responses to return.
2346         self.run_until(time::sleep(Duration::from_millis(POLL_RESPONSE_TIMEOUT))).await?;
2347 
2348         // Check if device was activated in Listen mode during
2349         // the poll interval, or if the discovery got cancelled.
2350         if self.state.rf_state != RfState::Discovery || self.state.rf_poll_responses.is_empty() {
2351             return Ok(());
2352         }
2353 
2354         // While polling, if the NFCC discovers just one Remote NFC Endpoint
2355         // that supports just one protocol, the NFCC SHALL try to automatically
2356         // activate it. The NFCC SHALL first establish any underlying
2357         // protocol(s) with the Remote NFC Endpoint that are needed by the
2358         // configured RF Interface. On completion, the NFCC SHALL activate the
2359         // RF Interface and send RF_INTF_ACTIVATED_NTF (Poll Mode) to the DH.
2360         // At this point, the state is changed to RFST_POLL_ACTIVE. If the
2361         // protocol activation is not successful, the NFCC SHALL send
2362         // CORE_GENERIC_ERROR_NTF to the DH with status
2363         // DISCOVERY_TARGET_ACTIVATION_FAILED and SHALL stay in the
2364         // RFST_DISCOVERY state.
2365         if self.state.rf_poll_responses.len() == 1 {
2366             let rf_protocol = self.state.rf_poll_responses[0].rf_protocol.into();
2367             let rf_interface = self.state.select_interface(RfMode::Poll, rf_protocol);
2368             return self.activate_poll_interface(0, rf_protocol, rf_interface).await;
2369         }
2370 
2371         debug!("[{}] received {} poll response(s)", self.id, self.state.rf_poll_responses.len());
2372 
2373         // While polling, if the NFCC discovers more than one Remote NFC
2374         // Endpoint, or a Remote NFC Endpoint that supports more than one RF
2375         // Protocol, it SHALL start sending RF_DISCOVER_NTF messages to the DH.
2376         // At this point, the state is changed to RFST_W4_ALL_DISCOVERIES.
2377         self.state.rf_state = RfState::WaitForHostSelect;
2378         let last_index = self.state.rf_poll_responses.len() - 1;
2379         for (index, response) in self.state.rf_poll_responses.clone().iter().enumerate() {
2380             self.send_control(nci::RfDiscoverNotificationBuilder {
2381                 rf_discovery_id: nci::RfDiscoveryId::from_index(index),
2382                 rf_protocol: response.rf_protocol.into(),
2383                 rf_technology_and_mode: match response.rf_technology {
2384                     rf::Technology::NfcA => nci::RfTechnologyAndMode::NfcAPassivePollMode,
2385                     rf::Technology::NfcB => nci::RfTechnologyAndMode::NfcBPassivePollMode,
2386                     _ => todo!(),
2387                 },
2388                 rf_technology_specific_parameters: response
2389                     .rf_technology_specific_parameters
2390                     .clone(),
2391                 notification_type: if index == last_index {
2392                     nci::DiscoverNotificationType::LastNotification
2393                 } else {
2394                     nci::DiscoverNotificationType::MoreNotifications
2395                 },
2396             })
2397             .await?
2398         }
2399 
2400         Ok(())
2401     }
2402 
2403     /// Main NFCC instance routine.
run( id: u16, nci_stream: nci::StreamRefMut<'a>, nci_writer: nci::Writer, rf_rx: mpsc::UnboundedReceiver<rf::RfPacket>, rf_tx: mpsc::UnboundedSender<rf::RfPacket>, ) -> Result<()>2404     pub async fn run(
2405         id: u16,
2406         nci_stream: nci::StreamRefMut<'a>,
2407         nci_writer: nci::Writer,
2408         rf_rx: mpsc::UnboundedReceiver<rf::RfPacket>,
2409         rf_tx: mpsc::UnboundedSender<rf::RfPacket>,
2410     ) -> Result<()> {
2411         // Local controller state.
2412         let mut nfcc = Controller::new(id, nci_stream, nci_writer, rf_rx, rf_tx);
2413 
2414         // Timer for tick events.
2415         let mut timer = time::interval(Duration::from_millis(1000));
2416 
2417         loop {
2418             nfcc.run_until(timer.tick()).await?;
2419             nfcc.tick().await?;
2420         }
2421     }
2422 }
2423