From 9631ab771dbf12babcfa00a9d1c7bb3344d724fe Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Sat, 7 Dec 2019 20:28:34 -0800 Subject: [PATCH] Add code (initial commit 2) --- .gitignore | 2 + Cargo.lock | 325 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + mraa-sys/Cargo.toml | 17 +++ mraa-sys/build.rs | 50 +++++++ mraa-sys/src/lib.rs | 27 ++++ mraa-sys/src/wrapper.h | 1 + mraa/Cargo.toml | 11 ++ mraa/src/lib.rs | 249 +++++++++++++++++++++++++++++++ 9 files changed, 684 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 mraa-sys/Cargo.toml create mode 100644 mraa-sys/build.rs create mode 100644 mraa-sys/src/lib.rs create mode 100644 mraa-sys/src/wrapper.h create mode 100644 mraa/Cargo.toml create mode 100644 mraa/src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9de102b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/*/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..69ded5b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,325 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bindgen" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cexpr" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clang-sys" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mraa" +version = "0.1.0" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mraa-sys 0.1.0", +] + +[[package]] +name = "mraa-sys" +version = "0.1.0" +dependencies = [ + "bindgen 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-hash" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "termcolor" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wincolor" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum bindgen 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1c85344eb535a31b62f0af37be84441ba9e7f0f4111eb0530f43d15e513fe57" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" +"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" +"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" +"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..561f94a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["mraa-sys", "mraa"] diff --git a/mraa-sys/Cargo.toml b/mraa-sys/Cargo.toml new file mode 100644 index 0000000..c59c44a --- /dev/null +++ b/mraa-sys/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "mraa-sys" +description = "Generated bindings for Intel's mraa library for low speed device I/O" +authors = ["Alex Mikhalev "] +license = "MIT" +homepage = "" +version = "0.1.0" + +edition = "2018" +links = "mraa" +build = "build.rs" + +[build-dependencies] +bindgen = { version = "0.52", default-features = false, features = ["logging", "runtime"] } +pkg-config = "0.3" + +[dependencies] diff --git a/mraa-sys/build.rs b/mraa-sys/build.rs new file mode 100644 index 0000000..632af59 --- /dev/null +++ b/mraa-sys/build.rs @@ -0,0 +1,50 @@ +extern crate bindgen; +extern crate pkg_config; + +use std::env; +use std::path::PathBuf; + +fn main() { + let pkgconfig = pkg_config::Config::new(); + let mraa_config = pkgconfig + .probe("mraa") + .expect("pkg_config probe failed for mraa"); + + let _ = pkgconfig + .probe("json-c"); + // .expect("pkg_config probe failed for json-c"); + + // Tell cargo to invalidate the built crate whenever the wrapper changes + println!("cargo:rerun-if-changed=src/wrapper.h"); + + let mut clang_args: Vec = Vec::new(); + for include_dir in &mraa_config.include_paths { + clang_args.push("-I".to_owned()); + clang_args.push(include_dir.to_str().unwrap().to_owned()); + } + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let mraa_bindings = bindgen::Builder::default() + .clang_args(clang_args) + // The input header we would like to generate + // bindings for. + .header("src/wrapper.h") + .whitelist_type("mraa_.*") + .whitelist_function("mraa_.*") + .whitelist_var("mraa_.*") + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + mraa_bindings + .write_to_file(out_path.join("mraa_bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/mraa-sys/src/lib.rs b/mraa-sys/src/lib.rs new file mode 100644 index 0000000..d85b1f5 --- /dev/null +++ b/mraa-sys/src/lib.rs @@ -0,0 +1,27 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +//! A crate with bindings generated by +//! [`bindgen`](https://github.com/rust-lang/rust-bindgen) for the Intel `mraa` +//! library for low-speed IO communication. +//! +//! # Cross compilation +//! This package uses [pkg_config](https://docs.rs/pkg-config/0.3.17/pkg_config/) +//! to find the location of `mraa` headers and libraries, so by setting the +//! appropriate environment variables, it is possible to cross compile this +//! library for other systems. +//! +//! Example for cross compiling to BeagleBone: +//! ```bash +//! SYSROOT=/path/to/sysroot +//! export PKG_CONFIG_SYSROOT_DIR="$SYSROOT" +//! export PKG_CONFIG_LIBDIR="$SYSROOT/usr/lib/arm-linux-gnueabihf/pkgconfig" +//! export PKG_CONFIG_ALLOW_CROSS=1 +//! export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 +//! export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 +//! cargo build --target=armv7-unknown-linux-gnueabihf +//! ``` + +include!(concat!(env!("OUT_DIR"), "/mraa_bindings.rs")); diff --git a/mraa-sys/src/wrapper.h b/mraa-sys/src/wrapper.h new file mode 100644 index 0000000..8fcffd4 --- /dev/null +++ b/mraa-sys/src/wrapper.h @@ -0,0 +1 @@ +#include diff --git a/mraa/Cargo.toml b/mraa/Cargo.toml new file mode 100644 index 0000000..98b4801 --- /dev/null +++ b/mraa/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mraa" +version = "0.1.0" +authors = ["Alex Mikhalev "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +mraa-sys = { path = "../mraa-sys" } +libc = "0.2.66" diff --git a/mraa/src/lib.rs b/mraa/src/lib.rs new file mode 100644 index 0000000..19d51a3 --- /dev/null +++ b/mraa/src/lib.rs @@ -0,0 +1,249 @@ +extern crate libc; +extern crate mraa_sys; + +use std::fmt; + +const MRAA_RESULT_CHECK_SYSLOG: mraa_sys::mraa_result_t = 10000; + +#[derive(Debug)] +pub struct Error { + inner: mraa_sys::mraa_result_t, + operation: &'static str, +} + +impl Error { + fn new_check_syslog(operation: &'static str) -> Self { + Self { + inner: MRAA_RESULT_CHECK_SYSLOG, + operation, + } + } + + pub fn raw_code(&self) -> mraa_sys::mraa_result_t { + self.inner + } + + pub fn operation(&self) -> &'static str { + self.operation + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "MRAA error on {}: ", self.operation)?; + match self.inner { + mraa_sys::mraa_result_t_MRAA_SUCCESS => write!(f, "Success"), + mraa_sys::mraa_result_t_MRAA_ERROR_FEATURE_NOT_IMPLEMENTED => { + write!(f, "Feature not implemented") + } + mraa_sys::mraa_result_t_MRAA_ERROR_FEATURE_NOT_SUPPORTED => { + write!(f, "Feature not supported by HW") + } + mraa_sys::mraa_result_t_MRAA_ERROR_INVALID_PARAMETER => write!(f, "Parameter invalid"), + mraa_sys::mraa_result_t_MRAA_ERROR_INVALID_RESOURCE => write!(f, "Resource invalid"), + MRAA_RESULT_CHECK_SYSLOG => write!(f, "Unknown error, check syslog for error message"), + unk => write!(f, "Unknown MRAA error: {}", unk), + } + } +} + +impl std::error::Error for Error {} + +pub type Result = std::result::Result; + +fn handle_result(inner: mraa_sys::mraa_result_t, operation: &'static str) -> self::Result<()> { + if inner == mraa_sys::mraa_result_t_MRAA_SUCCESS { + Ok(()) + } else { + Err(Error { inner, operation }) + } +} + +pub fn init() -> self::Result<()> { + handle_result(unsafe { mraa_sys::mraa_init() }, "init") +} + +// TODO: this crashes sometimes for some reason +pub unsafe fn deinit() { + // unsafe { mraa_sys::mraa_deinit() }; + mraa_sys::mraa_deinit(); +} + +pub enum LogLevel { + Emergency = 0, + Alert = 1, + Critical = 2, + Error = 3, + Warning = 4, + Notice = 5, + Info = 6, + Debug = 7, +} + +pub fn set_log_level(log_level: LogLevel) -> self::Result<()> { + handle_result( + unsafe { mraa_sys::mraa_set_log_level(log_level as i32) }, + "set_log_level", + ) +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum GpioDirection { + Out, + In, + OutHigh, + OutLow, +} + +impl GpioDirection { + fn into_raw(self) -> mraa_sys::mraa_gpio_dir_t { + use GpioDirection::*; + match self { + Out => mraa_sys::mraa_gpio_dir_t_MRAA_GPIO_OUT, + In => mraa_sys::mraa_gpio_dir_t_MRAA_GPIO_IN, + OutHigh => mraa_sys::mraa_gpio_dir_t_MRAA_GPIO_OUT_HIGH, + OutLow => mraa_sys::mraa_gpio_dir_t_MRAA_GPIO_OUT_LOW, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum GpioEdge { + NoEdge, + Both, + Rising, + Falling, +} + +impl GpioEdge { + fn into_raw(self) -> mraa_sys::mraa_gpio_edge_t { + use GpioEdge::*; + match self { + NoEdge => mraa_sys::mraa_gpio_edge_t_MRAA_GPIO_EDGE_NONE, + Both => mraa_sys::mraa_gpio_edge_t_MRAA_GPIO_EDGE_BOTH, + Rising => mraa_sys::mraa_gpio_edge_t_MRAA_GPIO_EDGE_RISING, + Falling => mraa_sys::mraa_gpio_edge_t_MRAA_GPIO_EDGE_FALLING, + } + } +} + +pub struct Gpio { + inner: mraa_sys::mraa_gpio_context, + isr_callback: Option>, +} + +impl Gpio { + pub fn new(pin: i32) -> Result { + let inner = unsafe { mraa_sys::mraa_gpio_init(pin) }; + if inner.is_null() { + Err(Error::new_check_syslog("Gpio::new")) + } else { + Ok(Self { + inner, + isr_callback: None, + }) + } + } + + pub fn set_dir(&mut self, dir: GpioDirection) -> Result<()> { + handle_result( + unsafe { mraa_sys::mraa_gpio_dir(self.inner, dir.into_raw()) }, + "Gpio::set_dir", + ) + } + + pub fn read(&mut self) -> Result { + match unsafe { mraa_sys::mraa_gpio_read(self.inner) } { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(Error::new_check_syslog("Gpio::read")), + } + } + + pub fn set_isr(&mut self, edge: GpioEdge, callback: F) -> Result<()> + where + F: FnMut() + 'static + Send + Sync, + { + if self.isr_callback.is_some() { + let _ = self.remove_isr(); + } + self.isr_callback = Some(Box::new(callback)); + + let data = self.isr_callback.as_mut().unwrap().as_mut() as *mut _; + let result = unsafe { + mraa_sys::mraa_gpio_isr( + self.inner, + edge.into_raw(), + Some(call_closure::), + data as *mut _, + ) + }; + handle_result(result, "Gpio::set_isr") + } + + pub fn remove_isr(&mut self) -> Result<()> { + let result = unsafe { mraa_sys::mraa_gpio_isr_exit(self.inner) }; + self.isr_callback = None; + handle_result(result, "Gpio::remove_isr") + } +} + +unsafe extern "C" fn call_closure(data: *mut libc::c_void) +where + F: FnMut(), +{ + let callback_ptr = data as *mut F; + let callback = &mut *callback_ptr; + callback(); +} + +impl Drop for Gpio { + fn drop(&mut self) { + unsafe { mraa_sys::mraa_gpio_close(self.inner) }; + } +} + +pub struct Aio { + inner: mraa_sys::mraa_aio_context, +} + +impl Aio { + pub fn new(pin: u32) -> Result { + let inner = unsafe { mraa_sys::mraa_aio_init(pin) }; + if inner.is_null() { + Err(Error::new_check_syslog("Aio::new")) + } else { + Ok(Self { inner }) + } + } + + pub fn read(&mut self) -> Result { + match unsafe { mraa_sys::mraa_aio_read(self.inner) } { + -1 => Err(Error::new_check_syslog("Aio::read")), + value => Ok(value), + } + } + + pub fn read_float(&mut self) -> Result { + let value = unsafe { mraa_sys::mraa_aio_read_float(self.inner) }; + if value < 0.0 { + Err(Error::new_check_syslog("Aio::read_float")) + } else { + Ok(value) + } + } +} + +impl Drop for Aio { + fn drop(&mut self) { + unsafe { mraa_sys::mraa_aio_close(self.inner) }; + } +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +}