• 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 //! Implementation of the HAl that talks to NFC controller over Android's HIDL
16 use crate::internal::InnerHal;
17 #[allow(unused)]
18 use crate::{is_control_packet, Hal, HalEvent, HalEventRegistry, HalEventStatus, Result};
19 use lazy_static::lazy_static;
20 use log::{debug, error};
21 use nfc_packets::nci::{DataPacket, NciPacket, Packet};
22 use std::sync::Mutex;
23 use tokio::select;
24 use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
25 use tokio::sync::oneshot;
26 
27 /// Initialize the module
init() -> Hal28 pub async fn init() -> Hal {
29     let (raw_hal, inner_hal) = InnerHal::new();
30     let (hal_open_evt_tx, hal_open_evt_rx) = oneshot::channel::<ffi::NfcStatus>();
31     let (hal_close_evt_tx, hal_close_evt_rx) = oneshot::channel::<ffi::NfcStatus>();
32     *CALLBACKS.lock().unwrap() = Some(Callbacks {
33         hal_open_evt_tx: Some(hal_open_evt_tx),
34         hal_close_evt_tx: Some(hal_close_evt_tx),
35         in_cmd_tx: inner_hal.in_cmd_tx,
36         in_data_tx: inner_hal.in_data_tx,
37     });
38     ffi::start_hal();
39     hal_open_evt_rx.await.unwrap();
40 
41     tokio::spawn(dispatch_outgoing(
42         raw_hal.hal_events.clone(),
43         inner_hal.out_cmd_rx,
44         inner_hal.out_data_rx,
45         hal_close_evt_rx,
46     ));
47 
48     raw_hal
49 }
50 
51 #[cxx::bridge(namespace = nfc::hal)]
52 // TODO Either use or remove these functions, this shouldn't be the long term state
53 #[allow(dead_code)]
54 mod ffi {
55 
56     #[repr(u32)]
57     #[derive(Debug)]
58     enum NfcEvent {
59         OPEN_CPLT = 0,
60         CLOSE_CPLT = 1,
61         POST_INIT_CPLT = 2,
62         PRE_DISCOVER_CPLT = 3,
63         REQUEST_CONTROL = 4,
64         RELEASE_CONTROL = 5,
65         ERROR = 6,
66         HCI_NETWORK_RESET = 7,
67     }
68 
69     #[repr(u32)]
70     #[derive(Debug)]
71     enum NfcStatus {
72         OK = 0,
73         FAILED = 1,
74         ERR_TRANSPORT = 2,
75         ERR_CMD_TIMEOUT = 3,
76         REFUSED = 4,
77     }
78 
79     unsafe extern "C++" {
80         include!("hal/ffi/hidl.h");
start_hal()81         fn start_hal();
stop_hal()82         fn stop_hal();
send_command(data: &[u8])83         fn send_command(data: &[u8]);
84 
85         #[namespace = "android::hardware::nfc::V1_1"]
86         type NfcEvent;
87 
88         #[namespace = "android::hardware::nfc::V1_0"]
89         type NfcStatus;
90     }
91 
92     extern "Rust" {
on_event(evt: NfcEvent, status: NfcStatus)93         fn on_event(evt: NfcEvent, status: NfcStatus);
on_data(data: &[u8])94         fn on_data(data: &[u8]);
95     }
96 }
97 
98 impl From<ffi::NfcStatus> for HalEventStatus {
from(ffi_nfc_status: ffi::NfcStatus) -> Self99     fn from(ffi_nfc_status: ffi::NfcStatus) -> Self {
100         match ffi_nfc_status {
101             ffi::NfcStatus::OK => HalEventStatus::Success,
102             ffi::NfcStatus::FAILED => HalEventStatus::Failed,
103             ffi::NfcStatus::ERR_TRANSPORT => HalEventStatus::TransportError,
104             ffi::NfcStatus::ERR_CMD_TIMEOUT => HalEventStatus::Timeout,
105             ffi::NfcStatus::REFUSED => HalEventStatus::Refused,
106             _ => HalEventStatus::Failed,
107         }
108     }
109 }
110 
111 struct Callbacks {
112     hal_open_evt_tx: Option<oneshot::Sender<ffi::NfcStatus>>,
113     hal_close_evt_tx: Option<oneshot::Sender<ffi::NfcStatus>>,
114     in_cmd_tx: UnboundedSender<NciPacket>,
115     in_data_tx: UnboundedSender<DataPacket>,
116 }
117 
118 lazy_static! {
119     static ref CALLBACKS: Mutex<Option<Callbacks>> = Mutex::new(None);
120 }
121 
on_event(evt: ffi::NfcEvent, status: ffi::NfcStatus)122 fn on_event(evt: ffi::NfcEvent, status: ffi::NfcStatus) {
123     debug!("got event: {:?} with status {:?}", evt, status);
124     let mut callbacks = CALLBACKS.lock().unwrap();
125     match evt {
126         ffi::NfcEvent::OPEN_CPLT => {
127             if let Some(evt_tx) = callbacks.as_mut().unwrap().hal_open_evt_tx.take() {
128                 evt_tx.send(status).unwrap();
129             }
130         }
131         ffi::NfcEvent::CLOSE_CPLT => {
132             if let Some(evt_tx) = callbacks.as_mut().unwrap().hal_close_evt_tx.take() {
133                 evt_tx.send(status).unwrap();
134             }
135         }
136         _ => error!("Unhandled HAL event {:?}", evt),
137     }
138 }
139 
on_data(data: &[u8])140 fn on_data(data: &[u8]) {
141     debug!("got packet: {:02x?}", data);
142     let callbacks = CALLBACKS.lock().unwrap();
143     if is_control_packet(data) {
144         match NciPacket::parse(data) {
145             Ok(p) => callbacks.as_ref().unwrap().in_cmd_tx.send(p).unwrap(),
146             Err(e) => error!("failure to parse response: {:?} data: {:02x?}", e, data),
147         }
148     } else {
149         match DataPacket::parse(data) {
150             Ok(p) => callbacks.as_ref().unwrap().in_data_tx.send(p).unwrap(),
151             Err(e) => error!("failure to parse response: {:?} data: {:02x?}", e, data),
152         }
153     }
154 }
155 
dispatch_outgoing( mut hal_events: HalEventRegistry, mut out_cmd_rx: UnboundedReceiver<NciPacket>, mut out_data_rx: UnboundedReceiver<DataPacket>, hal_close_evt_rx: oneshot::Receiver<ffi::NfcStatus>, )156 async fn dispatch_outgoing(
157     mut hal_events: HalEventRegistry,
158     mut out_cmd_rx: UnboundedReceiver<NciPacket>,
159     mut out_data_rx: UnboundedReceiver<DataPacket>,
160     hal_close_evt_rx: oneshot::Receiver<ffi::NfcStatus>,
161 ) {
162     loop {
163         select! {
164             Some(cmd) = out_cmd_rx.recv() => ffi::send_command(&cmd.to_bytes()),
165             Some(data) = out_data_rx.recv() => ffi::send_command(&data.to_bytes()),
166             else => break,
167         }
168     }
169     ffi::stop_hal();
170     let status = hal_close_evt_rx.await.unwrap();
171     if let Some(evt) = hal_events.unregister(HalEvent::CloseComplete).await {
172         evt.send(HalEventStatus::from(status)).unwrap();
173     }
174 }
175