fission_shell_winit/
nfc.rs1use fission_core::{
2 NfcAvailability, NfcEmulationRequest, NfcError, NfcRecord, NfcScanRequest, NfcSessionReceipt,
3 NfcTag, NfcTechnology, NfcWriteRequest, CANCEL_NFC_SESSION, EMULATE_NFC_TAG,
4 GET_NFC_AVAILABILITY, SCAN_NFC_TAG, WRITE_NFC_TAG,
5};
6use fission_shell::async_host::AsyncRegistry;
7use std::sync::Arc;
8
9pub trait NfcHost: Send + Sync + 'static {
11 fn availability(&self) -> Result<NfcAvailability, NfcError>;
13 fn scan_tag(&self, request: NfcScanRequest) -> Result<NfcTag, NfcError>;
18 fn write_tag(&self, request: NfcWriteRequest) -> Result<NfcSessionReceipt, NfcError>;
20 fn emulate_tag(&self, request: NfcEmulationRequest) -> Result<NfcSessionReceipt, NfcError>;
22 fn cancel_session(&self) -> Result<(), NfcError>;
24}
25
26#[derive(Debug, Default)]
28pub struct UnsupportedNfcHost;
29
30impl NfcHost for UnsupportedNfcHost {
31 fn availability(&self) -> Result<NfcAvailability, NfcError> {
32 Ok(NfcAvailability::default())
33 }
34
35 fn scan_tag(&self, _request: NfcScanRequest) -> Result<NfcTag, NfcError> {
36 Err(NfcError::unsupported("scan_tag"))
37 }
38
39 fn write_tag(&self, _request: NfcWriteRequest) -> Result<NfcSessionReceipt, NfcError> {
40 Err(NfcError::unsupported("write_tag"))
41 }
42
43 fn emulate_tag(&self, _request: NfcEmulationRequest) -> Result<NfcSessionReceipt, NfcError> {
44 Err(NfcError::unsupported("emulate_tag"))
45 }
46
47 fn cancel_session(&self) -> Result<(), NfcError> {
48 Err(NfcError::unsupported("cancel_session"))
49 }
50}
51
52#[derive(Debug, Clone)]
54pub struct MemoryNfcHost {
55 tag: NfcTag,
56}
57
58impl MemoryNfcHost {
59 pub fn new(tag: NfcTag) -> Self {
60 Self { tag }
61 }
62}
63
64impl Default for MemoryNfcHost {
65 fn default() -> Self {
66 Self {
67 tag: NfcTag {
68 id: Some(vec![0xF1, 0x55, 0x10, 0x01]),
69 technologies: vec![NfcTechnology::Ndef],
70 records: vec![NfcRecord::uri("fission://memory-nfc")],
71 raw_payload: None,
72 },
73 }
74 }
75}
76
77impl NfcHost for MemoryNfcHost {
78 fn availability(&self) -> Result<NfcAvailability, NfcError> {
79 Ok(NfcAvailability {
80 supported: true,
81 enabled: true,
82 read: true,
83 write: true,
84 card_emulation: true,
85 })
86 }
87
88 fn scan_tag(&self, _request: NfcScanRequest) -> Result<NfcTag, NfcError> {
89 Ok(self.tag.clone())
90 }
91
92 fn write_tag(&self, request: NfcWriteRequest) -> Result<NfcSessionReceipt, NfcError> {
93 Ok(NfcSessionReceipt {
94 session_id: Some(format!("memory-nfc-write-{}", request.records.len())),
95 completed: true,
96 })
97 }
98
99 fn emulate_tag(&self, request: NfcEmulationRequest) -> Result<NfcSessionReceipt, NfcError> {
100 Ok(NfcSessionReceipt {
101 session_id: Some(format!("memory-nfc-emulate-{}", request.records.len())),
102 completed: true,
103 })
104 }
105
106 fn cancel_session(&self) -> Result<(), NfcError> {
107 Ok(())
108 }
109}
110
111pub(crate) fn register_nfc_capabilities(
112 async_registry: &mut AsyncRegistry,
113 host: Arc<dyn NfcHost>,
114) {
115 let availability_host = host.clone();
116 async_registry.register_operation_capability(GET_NFC_AVAILABILITY, move |(), _| {
117 let host = availability_host.clone();
118 async move { host.availability() }
119 });
120
121 let scan_host = host.clone();
122 async_registry.register_operation_capability(SCAN_NFC_TAG, move |request, _| {
123 let host = scan_host.clone();
124 async move { host.scan_tag(request) }
125 });
126
127 let write_host = host.clone();
128 async_registry.register_operation_capability(WRITE_NFC_TAG, move |request, _| {
129 let host = write_host.clone();
130 async move { host.write_tag(request) }
131 });
132
133 let emulate_host = host.clone();
134 async_registry.register_operation_capability(EMULATE_NFC_TAG, move |request, _| {
135 let host = emulate_host.clone();
136 async move { host.emulate_tag(request) }
137 });
138
139 async_registry.register_operation_capability(CANCEL_NFC_SESSION, move |(), _| {
140 let host = host.clone();
141 async move { host.cancel_session() }
142 });
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn unsupported_host_reports_unavailable() {
151 let host = UnsupportedNfcHost;
152 let availability = host.availability().unwrap();
153
154 assert!(!availability.supported);
155 assert!(host.scan_tag(NfcScanRequest::default()).is_err());
156 }
157
158 #[test]
159 fn memory_host_scans_and_writes() {
160 let host = MemoryNfcHost::default();
161 let tag = host.scan_tag(NfcScanRequest::default()).unwrap();
162 assert_eq!(tag.technologies, vec![NfcTechnology::Ndef]);
163
164 let receipt = host
165 .write_tag(NfcWriteRequest {
166 records: vec![NfcRecord::text("en", "ok")],
167 ..Default::default()
168 })
169 .unwrap();
170 assert!(receipt.completed);
171 }
172}