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