Raw FFI bindings to the public libfreefare C API.
This crate intentionally stays low level. It exposes the upstream ABI for use by higher-level Rust wrappers and NFC tooling, and does not add safe abstractions over tag access, authentication, or memory management.
Version 1.0.0 is a breaking cleanup release:
- The binding surface now tracks the public
freefare.hAPI instead of exposing generator artifacts and non-header symbols. - Opaque native types such as
MifareTag,MifareDESFireKey,Mad, andMifareDESFireAIDare no longer represented as fake Rust structs with internals. - Old
Struct_*andEnum_*bindgen names were replaced with stable Rust-facing FFI names. - Unsound
Defaultimplementations based onmem::zeroed()were removed. - Modern Rust FFI types are used throughout (
c_char,c_int,c_void,u8,u16,u32,usize,isize). - The crate now ships smoke tests for layout assumptions and native linking.
You need both libfreefare and libnfc installed on the system.
brew install libfreefare libnfcsudo apt install libfreefare-dev libnfc-devbuild.rs links against freefare. The nfc-sys dependency links libnfc.
By default it checks common Homebrew and Linux library directories for libfreefare. If your libfreefare installation lives elsewhere, set either the preferred LIBFREEFARE_LIB_DIR variable or the legacy LIBFREEFARE_PATH variable:
export LIBFREEFARE_LIB_DIR=/custom/prefix/lib[dependencies]
freefare-sys = "1"
libc = "0.2"
nfc-sys = "1"use std::ffi::CStr;
use std::ptr;
fn main() {
unsafe {
let mut context: *mut nfc_sys::nfc_context = ptr::null_mut();
nfc_sys::nfc_init(&mut context);
assert!(!context.is_null());
let device = nfc_sys::nfc_open(context, ptr::null());
if device.is_null() {
nfc_sys::nfc_exit(context);
return;
}
let tags = freefare_sys::freefare_get_tags(device);
if !tags.is_null() && !(*tags).is_null() {
let tag = *tags;
let uid = freefare_sys::freefare_get_tag_uid(tag);
if !uid.is_null() {
println!("tag uid: {}", CStr::from_ptr(uid).to_string_lossy());
libc::free(uid.cast());
}
freefare_sys::freefare_free_tags(tags);
}
nfc_sys::nfc_close(device);
nfc_sys::nfc_exit(context);
}
}This crate exposes raw C bindings. Callers are responsible for:
- Upholding all pointer validity and lifetime requirements from
libfreefare. - Freeing memory returned by the native library with the correct native deallocator.
- Ensuring linked
libfreefareandlibnfcversions are ABI-compatible with the declarations in this crate.
The Rust crate version follows the Rust FFI surface, not the upstream libfreefare release number. Breaking binding corrections or symbol removals may require a new major version even when the C library version is unchanged.
MIT