1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
//! Provides actual bindings and wrapper around VideoCore gencmd interface. //! //! The raw bindings are available in the [`ffi`](ffi) module. //! //! Currently implemented commands can be seen in [`gencmd::commands`](gencmd::commands) module. Note that //! since the gencmd interface is a simple textual protocol it can be used even without an explicit implementation (see [`Gencmd::send_cmd_raw`](gencmd::Gencmd::send_cmd_raw)). //! The advantage of implementing a command specifically is parsing of the response into an appropriate type. //! //! ## Usage //! //! There are two patterns this library supports out of the box: //! //! ### Unique instance //! //! The [`GencmdUnique`](gencmd::unique::GencmdUnique) convenience wrapper provides an easy way to create //! a unique instance to be used on one thread at a time. //! //! Note that there can ever only be one instance of the global context per-process. //! Attempting to create multiple instances returns an error. If you need access from multiple threads simultaneously //! consider using the global singleton or implementing a similar solution yourself. //! //! ``` //! use videocore_gencmd::prelude::*; //! fn main() -> Result<(), Box<dyn std::error::Error>> { //! let mut gencmd = GencmdUnique::new()?; //! //! let temperature = gencmd.send_cmd::<CmdMeasureTemp>()?; //! //! println!("VC temperature is: {}", temperature); //! //! Ok(()) //! } //! ``` //! //! ### Global multi-threaded instance //! //! The unique instance approach should be sufficient for most usecases. However, sometimes it is required //! to invoke gencmd interface from multiple threads at one time. For this there is the `global_singleton` feature //! that exposes a global, lazy-initialized, weak-pointed singleton and a convenience [`GencmdGlobal`](gencmd::global::GencmdGlobal). //! //! ``` //! use videocore_gencmd::prelude::*; //! fn main() { //! let temperature_measurer = //! std::thread::spawn(|| -> Result<(), Box<dyn std::error::Error + Send + Sync>> { //! let mut gencmd = GencmdGlobal::new()?; //! //! let mut limit = 3; //! while limit > 0 { //! let temperature = gencmd.send_cmd::<CmdMeasureTemp>()?; //! println!("VC temperature is: {}", temperature); //! //! std::thread::sleep(std::time::Duration::from_secs(1)); //! limit -= 1; //! } //! //! Ok(()) //! }); //! //! let freq_measurer = //! std::thread::spawn(|| -> Result<(), Box<dyn std::error::Error + Send + Sync>> { //! let mut gencmd = GencmdGlobal::new()?; //! //! let mut limit = 3; //! while limit > 0 { //! let frequency = gencmd.send_cmd::<CmdMeasureClockArm>()?; //! println!("Arm frequency is: {} Hz", frequency); //! //! std::thread::sleep(std::time::Duration::from_secs(1)); //! limit -= 1; //! } //! //! Ok(()) //! }); //! //! temperature_measurer.join().unwrap(); //! freq_measurer.join().unwrap(); //! } //! ``` //! //! ## Features //! //! ### `run_bindgen` //! //! Runs the bindgen in build.rs. Without this feature enabled the bindings previously generated and pasted into the sources //! are used instead as the bindgen cannot be used on all platforms. //! //! ### `mock_vc_ffi` //! //! FFI bindings naturally expect a library to link against. For testing purposes this is not always ideal, so this feature instead //! exposes C ABI functions that match the bindings and mock the interface to some extent. //! //! ### `cli_app` //! //! This feature gates optional crates needed to build the cli app which functionally mirrors the C binary `vcgencmd`. //! //! ### `global_singleton` //! //! Enables the global singleton implementation as described above. pub mod error; pub mod ffi; pub mod gencmd; pub mod global; pub mod prelude; #[cfg(test)] mod test { use std::sync::Once; static ONCE: Once = Once::new(); pub fn setup_global() { ONCE.call_once(|| { // edwardium_logger::Logger::new( // edwardium_logger::targets::stderr::StderrTarget::new(log::Level::Trace, Default::default()), // std::time::Instant::now() // ).init_boxed().expect("Could not initialize logger"); }); } }