Skip to main content

nfc_sys/
lib.rs

1#![allow(non_camel_case_types, non_snake_case)]
2//! Raw Rust FFI bindings for libnfc.
3//!
4//! This crate follows the usual `*-sys` crate pattern: it exposes libnfc's C API
5//! with minimal translation and does not manage ownership, lifetimes, or error
6//! handling for you. Most useful calls are `unsafe` because callers must satisfy
7//! the same requirements as the corresponding native libnfc functions.
8//!
9//! The `nfc_context`, `nfc_device`, and `nfc_driver` types are opaque because
10//! libnfc treats them as incomplete public types. Use the accessor and lifecycle
11//! functions exported by libnfc instead of relying on their internal layout.
12//!
13//! # Linking
14//!
15//! The build script links against a system-provided `libnfc`. On macOS it checks
16//! common Homebrew locations. For custom installations, set `LIBNFC_LIB_DIR` to
17//! the directory containing the native library.
18//!
19//! # Example
20//!
21//! ```no_run
22//! use std::ffi::CStr;
23//! use std::ptr;
24//!
25//! use nfc_sys::{nfc_exit, nfc_init, nfc_version};
26//!
27//! unsafe {
28//!     let mut context = ptr::null_mut();
29//!     nfc_init(&mut context);
30//!
31//!     if !context.is_null() {
32//!         let version = CStr::from_ptr(nfc_version()).to_string_lossy();
33//!         println!("libnfc version: {}", version);
34//!
35//!         nfc_exit(context);
36//!     }
37//! }
38//! ```
39
40extern crate libc;
41
42use libc::{c_char, c_int, c_void, size_t};
43
44pub const NFC_BUFSIZE_CONNSTRING: usize = 1024;
45
46pub const NFC_SUCCESS: c_int = 0;
47pub const NFC_EIO: c_int = -1;
48pub const NFC_EINVARG: c_int = -2;
49pub const NFC_EDEVNOTSUPP: c_int = -3;
50pub const NFC_ENOTSUCHDEV: c_int = -4;
51pub const NFC_EOVFLOW: c_int = -5;
52pub const NFC_ETIMEOUT: c_int = -6;
53pub const NFC_EOPABORTED: c_int = -7;
54pub const NFC_ENOTIMPL: c_int = -8;
55pub const NFC_ETGRELEASED: c_int = -10;
56pub const NFC_ERFTRANS: c_int = -20;
57pub const NFC_EMFCAUTHFAIL: c_int = -30;
58pub const NFC_ESOFT: c_int = -80;
59pub const NFC_ECHIP: c_int = -90;
60
61/// Opaque libnfc context handle.
62#[repr(C)]
63pub struct nfc_context {
64    _private: [u8; 0],
65}
66
67/// Opaque libnfc device handle.
68#[repr(C)]
69pub struct nfc_device {
70    _private: [u8; 0],
71}
72
73/// Opaque libnfc driver handle.
74#[repr(C)]
75pub struct nfc_driver {
76    _private: [u8; 0],
77}
78
79pub type nfc_connstring = [c_char; NFC_BUFSIZE_CONNSTRING];
80
81#[repr(C)]
82#[derive(Copy, Clone, Debug, Eq, PartialEq)]
83pub enum nfc_property {
84    NP_TIMEOUT_COMMAND = 0,
85    NP_TIMEOUT_ATR = 1,
86    NP_TIMEOUT_COM = 2,
87    NP_HANDLE_CRC = 3,
88    NP_HANDLE_PARITY = 4,
89    NP_ACTIVATE_FIELD = 5,
90    NP_ACTIVATE_CRYPTO1 = 6,
91    NP_INFINITE_SELECT = 7,
92    NP_ACCEPT_INVALID_FRAMES = 8,
93    NP_ACCEPT_MULTIPLE_FRAMES = 9,
94    NP_AUTO_ISO14443_4 = 10,
95    NP_EASY_FRAMING = 11,
96    NP_FORCE_ISO14443_A = 12,
97    NP_FORCE_ISO14443_B = 13,
98    NP_FORCE_SPEED_106 = 14,
99}
100
101#[repr(C)]
102#[derive(Copy, Clone, Debug, Eq, PartialEq)]
103pub enum nfc_dep_mode {
104    NDM_UNDEFINED = 0,
105    NDM_PASSIVE = 1,
106    NDM_ACTIVE = 2,
107}
108
109#[repr(C, packed)]
110#[derive(Copy, Clone)]
111pub struct nfc_dep_info {
112    pub abtNFCID3: [u8; 10],
113    pub btDID: u8,
114    pub btBS: u8,
115    pub btBR: u8,
116    pub btTO: u8,
117    pub btPP: u8,
118    pub abtGB: [u8; 48],
119    pub szGB: size_t,
120    pub ndm: nfc_dep_mode,
121}
122
123#[repr(C, packed)]
124#[derive(Copy, Clone)]
125pub struct nfc_iso14443a_info {
126    pub abtAtqa: [u8; 2],
127    pub btSak: u8,
128    pub szUidLen: size_t,
129    pub abtUid: [u8; 10],
130    pub szAtsLen: size_t,
131    pub abtAts: [u8; 254],
132}
133
134#[repr(C, packed)]
135#[derive(Copy, Clone)]
136pub struct nfc_felica_info {
137    pub szLen: size_t,
138    pub btResCode: u8,
139    pub abtId: [u8; 8],
140    pub abtPad: [u8; 8],
141    pub abtSysCode: [u8; 2],
142}
143
144#[repr(C, packed)]
145#[derive(Copy, Clone)]
146pub struct nfc_iso14443b_info {
147    pub abtPupi: [u8; 4],
148    pub abtApplicationData: [u8; 4],
149    pub abtProtocolInfo: [u8; 3],
150    pub ui8CardIdentifier: u8,
151}
152
153#[repr(C, packed)]
154#[derive(Copy, Clone)]
155pub struct nfc_iso14443bi_info {
156    pub abtDIV: [u8; 4],
157    pub btVerLog: u8,
158    pub btConfig: u8,
159    pub szAtrLen: size_t,
160    pub abtAtr: [u8; 33],
161}
162
163#[repr(C, packed)]
164#[derive(Copy, Clone)]
165pub struct nfc_iso14443biclass_info {
166    pub abtUID: [u8; 8],
167}
168
169#[repr(C, packed)]
170#[derive(Copy, Clone)]
171pub struct nfc_iso14443b2sr_info {
172    pub abtUID: [u8; 8],
173}
174
175#[repr(C, packed)]
176#[derive(Copy, Clone)]
177pub struct nfc_iso14443b2ct_info {
178    pub abtUID: [u8; 4],
179    pub btProdCode: u8,
180    pub btFabCode: u8,
181}
182
183#[repr(C, packed)]
184#[derive(Copy, Clone)]
185pub struct nfc_jewel_info {
186    pub btSensRes: [u8; 2],
187    pub btId: [u8; 4],
188}
189
190#[repr(C, packed)]
191#[derive(Copy, Clone)]
192pub struct nfc_barcode_info {
193    pub szDataLen: size_t,
194    pub abtData: [u8; 32],
195}
196
197#[repr(C, packed)]
198#[derive(Copy, Clone)]
199pub union nfc_target_info {
200    pub nai: nfc_iso14443a_info,
201    pub nfi: nfc_felica_info,
202    pub nbi: nfc_iso14443b_info,
203    pub nii: nfc_iso14443bi_info,
204    pub nsi: nfc_iso14443b2sr_info,
205    pub nci: nfc_iso14443b2ct_info,
206    pub nji: nfc_jewel_info,
207    pub ndi: nfc_dep_info,
208    pub nti: nfc_barcode_info,
209    pub nhi: nfc_iso14443biclass_info,
210}
211
212#[repr(C)]
213#[derive(Copy, Clone, Debug, Eq, PartialEq)]
214pub enum nfc_baud_rate {
215    NBR_UNDEFINED = 0,
216    NBR_106 = 1,
217    NBR_212 = 2,
218    NBR_424 = 3,
219    NBR_847 = 4,
220}
221
222#[repr(C)]
223#[derive(Copy, Clone, Debug, Eq, PartialEq)]
224pub enum nfc_modulation_type {
225    NMT_ISO14443A = 1,
226    NMT_JEWEL = 2,
227    NMT_ISO14443B = 3,
228    NMT_ISO14443BI = 4,
229    NMT_ISO14443B2SR = 5,
230    NMT_ISO14443B2CT = 6,
231    NMT_FELICA = 7,
232    NMT_DEP = 8,
233    NMT_BARCODE = 9,
234    NMT_ISO14443BICLASS = 10,
235}
236
237pub const NMT_END_ENUM: nfc_modulation_type = nfc_modulation_type::NMT_ISO14443BICLASS;
238
239#[repr(C)]
240#[derive(Copy, Clone, Debug, Eq, PartialEq)]
241pub enum nfc_mode {
242    N_TARGET = 0,
243    N_INITIATOR = 1,
244}
245
246#[repr(C, packed)]
247#[derive(Copy, Clone)]
248pub struct nfc_modulation {
249    pub nmt: nfc_modulation_type,
250    pub nbr: nfc_baud_rate,
251}
252
253#[repr(C, packed)]
254#[derive(Copy, Clone)]
255pub struct nfc_target {
256    pub nti: nfc_target_info,
257    pub nm: nfc_modulation,
258}
259
260#[repr(C)]
261pub struct nfc_emulator {
262    pub target: *mut nfc_target,
263    pub state_machine: *mut nfc_emulation_state_machine,
264    pub user_data: *mut c_void,
265}
266
267#[repr(C)]
268pub struct nfc_emulation_state_machine {
269    pub io: Option<
270        unsafe extern "C" fn(
271            emulator: *mut nfc_emulator,
272            data_in: *const u8,
273            data_in_len: size_t,
274            data_out: *mut u8,
275            data_out_len: size_t,
276        ) -> c_int,
277    >,
278    pub data: *mut c_void,
279}
280
281#[link(name = "nfc")]
282extern "C" {
283    pub fn nfc_init(context: *mut *mut nfc_context);
284    pub fn nfc_exit(context: *mut nfc_context);
285    pub fn nfc_register_driver(driver: *const nfc_driver) -> c_int;
286
287    pub fn nfc_open(context: *mut nfc_context, connstring: *const c_char) -> *mut nfc_device;
288    pub fn nfc_close(pnd: *mut nfc_device);
289    pub fn nfc_abort_command(pnd: *mut nfc_device) -> c_int;
290    pub fn nfc_list_devices(
291        context: *mut nfc_context,
292        connstrings: *mut nfc_connstring,
293        connstrings_len: size_t,
294    ) -> size_t;
295    pub fn nfc_idle(pnd: *mut nfc_device) -> c_int;
296
297    pub fn nfc_initiator_init(pnd: *mut nfc_device) -> c_int;
298    pub fn nfc_initiator_init_secure_element(pnd: *mut nfc_device) -> c_int;
299    pub fn nfc_initiator_select_passive_target(
300        pnd: *mut nfc_device,
301        nm: nfc_modulation,
302        pbtInitData: *const u8,
303        szInitData: size_t,
304        pnt: *mut nfc_target,
305    ) -> c_int;
306    pub fn nfc_initiator_list_passive_targets(
307        pnd: *mut nfc_device,
308        nm: nfc_modulation,
309        ant: *mut nfc_target,
310        szTargets: size_t,
311    ) -> c_int;
312    pub fn nfc_initiator_poll_target(
313        pnd: *mut nfc_device,
314        pnmTargetTypes: *const nfc_modulation,
315        szTargetTypes: size_t,
316        uiPollNr: u8,
317        uiPeriod: u8,
318        pnt: *mut nfc_target,
319    ) -> c_int;
320    pub fn nfc_initiator_select_dep_target(
321        pnd: *mut nfc_device,
322        ndm: nfc_dep_mode,
323        nbr: nfc_baud_rate,
324        pndiInitiator: *const nfc_dep_info,
325        pnt: *mut nfc_target,
326        timeout: c_int,
327    ) -> c_int;
328    pub fn nfc_initiator_poll_dep_target(
329        pnd: *mut nfc_device,
330        ndm: nfc_dep_mode,
331        nbr: nfc_baud_rate,
332        pndiInitiator: *const nfc_dep_info,
333        pnt: *mut nfc_target,
334        timeout: c_int,
335    ) -> c_int;
336    pub fn nfc_initiator_deselect_target(pnd: *mut nfc_device) -> c_int;
337    pub fn nfc_initiator_transceive_bytes(
338        pnd: *mut nfc_device,
339        pbtTx: *const u8,
340        szTx: size_t,
341        pbtRx: *mut u8,
342        szRx: size_t,
343        timeout: c_int,
344    ) -> c_int;
345    pub fn nfc_initiator_transceive_bits(
346        pnd: *mut nfc_device,
347        pbtTx: *const u8,
348        szTxBits: size_t,
349        pbtTxPar: *const u8,
350        pbtRx: *mut u8,
351        szRx: size_t,
352        pbtRxPar: *mut u8,
353    ) -> c_int;
354    pub fn nfc_initiator_transceive_bytes_timed(
355        pnd: *mut nfc_device,
356        pbtTx: *const u8,
357        szTx: size_t,
358        pbtRx: *mut u8,
359        szRx: size_t,
360        cycles: *mut u32,
361    ) -> c_int;
362    pub fn nfc_initiator_transceive_bits_timed(
363        pnd: *mut nfc_device,
364        pbtTx: *const u8,
365        szTxBits: size_t,
366        pbtTxPar: *const u8,
367        pbtRx: *mut u8,
368        szRx: size_t,
369        pbtRxPar: *mut u8,
370        cycles: *mut u32,
371    ) -> c_int;
372    pub fn nfc_initiator_target_is_present(pnd: *mut nfc_device, pnt: *const nfc_target) -> c_int;
373
374    pub fn nfc_target_init(
375        pnd: *mut nfc_device,
376        pnt: *mut nfc_target,
377        pbtRx: *mut u8,
378        szRx: size_t,
379        timeout: c_int,
380    ) -> c_int;
381    pub fn nfc_target_send_bytes(
382        pnd: *mut nfc_device,
383        pbtTx: *const u8,
384        szTx: size_t,
385        timeout: c_int,
386    ) -> c_int;
387    pub fn nfc_target_receive_bytes(
388        pnd: *mut nfc_device,
389        pbtRx: *mut u8,
390        szRx: size_t,
391        timeout: c_int,
392    ) -> c_int;
393    pub fn nfc_target_send_bits(
394        pnd: *mut nfc_device,
395        pbtTx: *const u8,
396        szTxBits: size_t,
397        pbtTxPar: *const u8,
398    ) -> c_int;
399    pub fn nfc_target_receive_bits(
400        pnd: *mut nfc_device,
401        pbtRx: *mut u8,
402        szRx: size_t,
403        pbtRxPar: *mut u8,
404    ) -> c_int;
405
406    pub fn nfc_strerror(pnd: *const nfc_device) -> *const c_char;
407    pub fn nfc_strerror_r(pnd: *const nfc_device, buf: *mut c_char, buflen: size_t) -> c_int;
408    pub fn nfc_perror(pnd: *const nfc_device, s: *const c_char);
409    pub fn nfc_device_get_last_error(pnd: *const nfc_device) -> c_int;
410
411    pub fn nfc_device_get_name(pnd: *mut nfc_device) -> *const c_char;
412    pub fn nfc_device_get_connstring(pnd: *mut nfc_device) -> *const c_char;
413    pub fn nfc_device_get_supported_modulation(
414        pnd: *mut nfc_device,
415        mode: nfc_mode,
416        supported_mt: *mut *const nfc_modulation_type,
417    ) -> c_int;
418    pub fn nfc_device_get_supported_baud_rate(
419        pnd: *mut nfc_device,
420        nmt: nfc_modulation_type,
421        supported_br: *mut *const nfc_baud_rate,
422    ) -> c_int;
423    pub fn nfc_device_get_supported_baud_rate_target_mode(
424        pnd: *mut nfc_device,
425        nmt: nfc_modulation_type,
426        supported_br: *mut *const nfc_baud_rate,
427    ) -> c_int;
428
429    pub fn nfc_device_set_property_int(
430        pnd: *mut nfc_device,
431        property: nfc_property,
432        value: c_int,
433    ) -> c_int;
434    pub fn nfc_device_set_property_bool(
435        pnd: *mut nfc_device,
436        property: nfc_property,
437        bEnable: bool,
438    ) -> c_int;
439
440    pub fn iso14443a_crc(pbtData: *mut u8, szLen: size_t, pbtCrc: *mut u8);
441    pub fn iso14443a_crc_append(pbtData: *mut u8, szLen: size_t);
442    pub fn iso14443b_crc(pbtData: *mut u8, szLen: size_t, pbtCrc: *mut u8);
443    pub fn iso14443b_crc_append(pbtData: *mut u8, szLen: size_t);
444    pub fn iso14443a_locate_historical_bytes(
445        pbtAts: *mut u8,
446        szAts: size_t,
447        pszTk: *mut size_t,
448    ) -> *mut u8;
449
450    pub fn nfc_free(p: *mut c_void);
451    pub fn nfc_version() -> *const c_char;
452    pub fn nfc_device_get_information_about(pnd: *mut nfc_device, buf: *mut *mut c_char) -> c_int;
453
454    pub fn str_nfc_modulation_type(nmt: nfc_modulation_type) -> *const c_char;
455    pub fn str_nfc_baud_rate(nbr: nfc_baud_rate) -> *const c_char;
456    pub fn str_nfc_target(buf: *mut *mut c_char, pnt: *const nfc_target, verbose: bool) -> c_int;
457
458    pub fn nfc_emulate_target(
459        pnd: *mut nfc_device,
460        emulator: *mut nfc_emulator,
461        timeout: c_int,
462    ) -> c_int;
463}
464
465#[cfg(test)]
466mod tests {
467    use super::*;
468
469    #[test]
470    fn can_call_libnfc_version() {
471        let version = unsafe { nfc_version() };
472
473        assert!(!version.is_null());
474    }
475
476    #[test]
477    fn target_layout_matches_libnfc_1_8_on_64_bit() {
478        #[cfg(target_pointer_width = "64")]
479        {
480            assert_eq!(std::mem::size_of::<nfc_target_info>(), 283);
481            assert_eq!(std::mem::size_of::<nfc_modulation>(), 8);
482            assert_eq!(std::mem::size_of::<nfc_target>(), 291);
483            assert_eq!(std::mem::align_of::<nfc_target_info>(), 1);
484            assert_eq!(std::mem::align_of::<nfc_target>(), 1);
485        }
486    }
487}