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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
//! This crate uses [`bindgen`] to create bindings to the LinuxCNC HAL module. //! //! The high level, safe interface at [`linuxcnc-hal`] is recommended for user code. //! //! # Binding versions //! //! | This crate | LinuxCNC version | //! | --------------------------------------------------------- | ---------------------------------------------------------- | //! | [v0.1.6](https://crates.io/crates/linuxcnc-hal-sys/0.1.6) | [v2.7.15](http://linuxcnc.org/2020/01/03/LinuxCNC-2.7.15/) | //! //! # Examples //! //! All functions exported from this crate are `unsafe`, hence each example is wrapped in a big //! `unsafe` block for clarity. //! //! The LinuxCNC HAL requires a certain setup procedure to operate correctly. The basic program //! structure should be roughly as follows //! //! 1. Call [`hal_init`] to create a new HAL component //! 1. Register `SIGTERM` and `SIGINT` signals, likely with the [`signal_hook`] crate. LinuxCNC will //! hang if these signals are not registered. //! 1. Register pins with [`hal_pin_float_new`], [`hal_pin_u32_new`], etc //! 1. Call [`hal_ready`] to signal to LinuxCNC that the component is ready //! 1. Enter an infinite loop to continuously update input/output pin values and perform component //! logic //! //! These examples can be loaded into LinuxCNC using a HAL file similar to this: //! //! ```text //! loadusr -W /path/to/your/component/target/debug/comp_bin_name //! net input-1 spindle.0.speed-out pins.input-1 //! ``` //! //! ## Create an input pin //! //! This example creates a component called `pins` and registers an input pin to it that accepts a //! floating point value using [`hal_pin_float_new`]. Each HAL pin requires some memory allocated to //! store its value which is performed with [`hal_malloc`]. //! //! The example can be loaded into LinuxCNC using a HAL file similar to this: //! //! **Note that there is no error handling in this example for brevity.** //! //! ```rust,no_run //! use linuxcnc_hal_sys::*; //! use signal_hook::iterator::Signals; //! use std::ffi::CString; //! use std::mem; //! use std::thread; //! use std::time::Duration; //! //! unsafe { //! let id = hal_init(CString::new("pins").unwrap().as_ptr() as *const i8); //! //! println!("ID {}", id); //! //! let signals = Signals::new(&[signal_hook::SIGTERM, signal_hook::SIGINT]).unwrap(); //! //! let storage = hal_malloc(mem::size_of::<f64>() as i64) as *mut *mut f64; //! //! println!("Storage {:?}", storage); //! //! let pin_name = CString::new("pins.input-1").unwrap(); //! //! let ret = hal_pin_float_new( //! pin_name.as_ptr() as *const i8, //! hal_pin_dir_t_HAL_IN, //! storage, //! id, //! ); //! //! println!("Pin init {}", ret); //! //! let ret = hal_ready(id); //! //! println!("Ready {}", ret); //! //! while !signals.pending().any(|signal| match signal { //! signal_hook::SIGTERM | signal_hook::SIGINT | signal_hook::SIGKILL => true, //! _ => false, //! }) { //! println!("Input {:?}", **storage); //! //! thread::sleep(Duration::from_millis(500)); //! } //! } //! ``` //! //! ## Error handling //! //! Errors are handled in this crate the same way as in the C code. Some consts are exported like //! [`EINVAL`] and [`EPERM`] to allow matching of returned error codes. //! //! ```rust,no_run //! use linuxcnc_hal_sys::*; //! use signal_hook::iterator::Signals; //! use std::ffi::CString; //! use std::mem; //! use std::thread; //! use std::time::Duration; //! //! unsafe { //! let ret = hal_init(CString::new("pins").unwrap().as_ptr() as *const i8); //! //! // Check that component was created successfully //! let component_id = match ret { //! x if x == -(EINVAL as i32) => panic!("Failed to initialise component"), //! x if x == -(ENOMEM as i32) => panic!("Not enough memory to initialise component"), //! id if id > 0 => id, //! code => unreachable!("Hit unreachable error code {}", code), //! }; //! //! println!("Component registered with ID {}", component_id); //! //! let signals = Signals::new(&[signal_hook::SIGTERM, signal_hook::SIGINT]).unwrap(); //! //! let storage = hal_malloc(mem::size_of::<f64>() as i64) as *mut *mut f64; //! //! if storage.is_null() { //! panic!("Failed to allocate storage"); //! } //! //! let pin_name = CString::new("pins.input-1").unwrap(); //! //! let ret = hal_pin_float_new( //! pin_name.as_ptr() as *const i8, //! hal_pin_dir_t_HAL_IN, //! storage, //! component_id, //! ); //! //! // Check that pin was registered successfully //! match ret { //! 0 => println!("Pin registered successfully"), //! x if x == -(EINVAL as i32) => panic!("Failed to register pin"), //! x if x == -(EPERM as i32) => { //! panic!("HAL is locked. Register pins before calling hal_ready()`") //! } //! x if x == -(ENOMEM as i32) => panic!("Failed to register pin"), //! code => unreachable!("Hit unreachable error code {}", code), //! } //! //! let ret = hal_ready(component_id); //! //! // Check that component is ready //! match ret { //! 0 => println!("Component is ready"), //! x if x == -(EINVAL as i32) => panic!("HAL component was not found or is already ready"), //! code => unreachable!("Hit unreachable error code {}", code), //! } //! //! while !signals.pending().any(|signal| match signal { //! signal_hook::SIGTERM | signal_hook::SIGINT | signal_hook::SIGKILL => true, //! _ => false, //! }) { //! println!("Input {:?}", **storage); //! //! thread::sleep(Duration::from_millis(500)); //! } //! } //! ``` //! [`linuxcnc-hal`]: https://docs.rs/linuxcnc-hal //! [`bindgen`]: https://docs.rs/bindgen //! [`signal_hook`]: https://docs.rs/signal_hook #![deny(intra_doc_link_resolution_failure)] #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] mod check_readme; include!(concat!(env!("OUT_DIR"), "/bindings.rs"));