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