• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! NCI API module
16 
17 use crate::{CommandSender, Result};
18 use bytes::Bytes;
19 use log::debug;
20 use nfc_hal::{HalEvent, HalEventRegistry, HalEventStatus};
21 use nfc_packets::nci::{self, CommandBuilder, Opcode};
22 use nfc_packets::nci::{FeatureEnable, PacketBoundaryFlag, ResetType};
23 use nfc_packets::nci::{InitCommandBuilder, ResetCommandBuilder};
24 use nfc_packets::nci::{InitResponsePacket, ResponseChild};
25 use tokio::sync::oneshot;
26 
27 /// NCI API object to manage static API data
28 pub struct NciApi {
29     /// Command Sender external interface
30     commands: Option<CommandSender>,
31     /// The NFC response callback
32     callback: Option<fn(u16, &[u8])>,
33     /// HalEventRegistry is used to register for HAL events
34     hal_events: Option<HalEventRegistry>,
35     nfc_data: NfcData,
36 }
37 
38 struct NfcData {
39     init_response: Option<InitResponsePacket>,
40 }
41 
42 impl NciApi {
43     /// NciApi constructor
new() -> NciApi44     pub fn new() -> NciApi {
45         let nfc_data = NfcData { init_response: None };
46         NciApi { commands: None, callback: None, hal_events: None, nfc_data }
47     }
48 
49     /** ****************************************************************************
50      **
51      ** Function         nfc_enable
52      **
53      ** Description      This function enables NFC. Prior to calling NFC_Enable:
54      **                  - the NFCC must be powered up, and ready to receive
55      **                    commands.
56      **
57      **                  This function opens the NCI transport (if applicable),
58      **                  resets the NFC controller, and initializes the NFC
59      **                  subsystems.
60      **
61      **                  When the NFC startup procedure is completed, an
62      **                  NFC_ENABLE_REVT is returned to the application using the
63      **                  tNFC_RESPONSE_CBACK.
64      **
65      ** Returns          tNFC_STATUS
66      **
67      *******************************************************************************/
68     /// extern tNFC_STATUS NFC_Enable(tNFC_RESPONSE_CBACK* p_cback);
nfc_enable(&mut self, callback: fn(u16, &[u8]))69     pub async fn nfc_enable(&mut self, callback: fn(u16, &[u8])) {
70         let nci = crate::init().await;
71 
72         self.commands = Some(nci.commands);
73         self.callback = Some(callback);
74         self.hal_events = Some(nci.hal_events);
75     }
76     /** ****************************************************************************
77      **
78      ** Function         NFC_Disable
79      **
80      ** Description      This function performs clean up routines for shutting down
81      **                  NFC and closes the NCI transport (if using dedicated NCI
82      **                  transport).
83      **
84      **                  When the NFC shutdown procedure is completed, an
85      **                  NFC_DISABLED_REVT is returned to the application using the
86      **                  tNFC_RESPONSE_CBACK.
87      **
88      ** Returns          nothing
89      **
90      *******************************************************************************/
91     /// extern void NFC_Disable(void);
nfc_disable(&mut self)92     pub async fn nfc_disable(&mut self) {
93         let (tx, rx) = oneshot::channel::<HalEventStatus>();
94         if let Some(mut hr) = self.hal_events.take() {
95             hr.register(HalEvent::CloseComplete, tx).await;
96 
97             if let Some(cmd) = self.commands.take() {
98                 drop(cmd);
99             }
100             let status = rx.await.unwrap();
101             debug!("Shutdown complete {:?}.", status);
102 
103             if let Some(cb) = self.callback.take() {
104                 cb(1, &[]);
105             }
106         }
107     }
108 
109     /** ****************************************************************************
110      **
111      ** Function         NFC_Init
112      **
113      ** Description      This function initializes control blocks for NFC
114      **
115      ** Returns          nothing
116      **
117      *******************************************************************************/
118     /// extern void NFC_Init(tHAL_NFC_ENTRY* p_hal_entry_tbl);
nfc_init(&mut self) -> Result<()>119     pub async fn nfc_init(&mut self) -> Result<()> {
120         let pbf = PacketBoundaryFlag::CompleteOrFinal;
121         if let Some(cmd) = self.commands.as_mut() {
122             let reset = cmd
123                 .send_and_notify(
124                     ResetCommandBuilder { gid: 0, pbf, reset_type: ResetType::ResetConfig }
125                         .build()
126                         .into(),
127                 )
128                 .await?;
129             let _notification_packet = reset.notification.await?;
130             let init = cmd
131                 .send(
132                     InitCommandBuilder { gid: 0, pbf, feature_enable: FeatureEnable::Rfu }
133                         .build()
134                         .into(),
135                 )
136                 .await?;
137             if let ResponseChild::InitResponse(irp) = init.specialize() {
138                 self.nfc_data.init_response = Some(irp);
139             }
140         }
141         Ok(())
142     }
143 
144     /** *****************************************************************************
145      **
146      ** Function         NFC_GetLmrtSize
147      **
148      ** Description      Called by application wto query the Listen Mode Routing
149      **                  Table size supported by NFCC
150      **
151      ** Returns          Listen Mode Routing Table size
152      **
153      *******************************************************************************/
154     /// extern uint16_t NFC_GetLmrtSize(void);
nfc_get_lmrt_size(&mut self) -> u16155     pub async fn nfc_get_lmrt_size(&mut self) -> u16 {
156         if let Some(ir) = &self.nfc_data.init_response {
157             ir.get_max_rout_tbls_size()
158         } else {
159             0
160         }
161     }
162 
163     /** *****************************************************************************
164      **
165      ** Function         NFC_SetConfig
166      **
167      ** Description      This function is called to send the configuration parameter
168      **                  TLV to NFCC. The response from NFCC is reported by
169      **                  tNFC_RESPONSE_CBACK as NFC_SET_CONFIG_REVT.
170      **
171      ** Parameters       tlv_size - the length of p_param_tlvs.
172      **                  p_param_tlvs - the parameter ID/Len/Value list
173      **
174      ** Returns          tNFC_STATUS
175      **
176      *******************************************************************************/
177     /// extern tNFC_STATUS NFC_SetConfig(uint8_t tlv_size, uint8_t* p_param_tlvs);
nfc_set_config(&mut self, param_tlvs: &[u8]) -> Result<u8>178     pub async fn nfc_set_config(&mut self, param_tlvs: &[u8]) -> Result<u8> {
179         let pbf = PacketBoundaryFlag::CompleteOrFinal;
180         if let Some(cmd) = self.commands.as_mut() {
181             let rp = cmd
182                 .send(
183                     CommandBuilder {
184                         gid: 0,
185                         pbf,
186                         op: Opcode::CoreSetConfig,
187                         payload: Some(Bytes::copy_from_slice(param_tlvs)),
188                     }
189                     .build(),
190                 )
191                 .await?;
192             let raw = Bytes::from(rp);
193             if let Some(cb) = self.callback {
194                 cb(2, &raw[3..]);
195             }
196             Ok(raw[3])
197         } else {
198             Ok(nci::Status::NotInitialized as u8)
199         }
200     }
201 
202     /** *****************************************************************************
203      **
204      ** Function         NFC_GetConfig
205      **
206      ** Description      This function is called to retrieve the parameter TLV from
207      **                  NFCC. The response from NFCC is reported by
208      **                  tNFC_RESPONSE_CBACK as NFC_GET_CONFIG_REVT.
209      **
210      ** Parameters       num_ids - the number of parameter IDs
211      **                  p_param_ids - the parameter ID list.
212      **
213      ** Returns          tNFC_STATUS
214      **
215      *******************************************************************************/
216     /// extern tNFC_STATUS NFC_GetConfig(uint8_t num_ids, uint8_t* p_param_ids);
nfc_get_config(&mut self, param_tlvs: &[u8]) -> Result<u8>217     pub async fn nfc_get_config(&mut self, param_tlvs: &[u8]) -> Result<u8> {
218         let pbf = PacketBoundaryFlag::CompleteOrFinal;
219         if let Some(cmd) = self.commands.as_mut() {
220             let rp = cmd
221                 .send(
222                     CommandBuilder {
223                         gid: 0,
224                         pbf,
225                         op: Opcode::CoreGetConfig,
226                         payload: Some(Bytes::copy_from_slice(param_tlvs)),
227                     }
228                     .build(),
229                 )
230                 .await?;
231             let raw = Bytes::from(rp);
232             if let Some(cb) = self.callback {
233                 cb(3, &raw[3..]);
234             }
235             Ok(raw[3])
236         } else {
237             Ok(nci::Status::NotInitialized as u8)
238         }
239     }
240 }
241 
242 impl Default for NciApi {
default() -> Self243     fn default() -> Self {
244         Self::new()
245     }
246 }
247