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, ¶meter.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