rust_lirc_client_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5use std::{
6    ffi::{CStr, CString},
7    mem::MaybeUninit,
8};
9
10include!("./bindings.rs");
11
12pub fn readconfig(path: Option<String>) -> Result<lirc_config, std::io::Error> {
13    let c_path = path.map(|p| CString::new(p).unwrap());
14    let c_str = match c_path {
15        Some(p) => p.as_ptr(),
16        None => std::ptr::null(),
17    };
18
19    unsafe {
20        let mut raw = MaybeUninit::uninit();
21        let ret = lirc_readconfig(c_str, raw.as_mut_ptr(), None);
22
23        if ret != 0 {
24            return Err(std::io::Error::last_os_error());
25        }
26
27        Ok(std::ptr::read(raw.assume_init()))
28    }
29}
30
31pub fn readconfig_only(path: Option<&str>) -> Result<lirc_config, i32> {
32    let c_path = path.map(|p| CString::new(p).unwrap());
33    let c_str = match c_path {
34        Some(p) => p.as_ptr(),
35        None => std::ptr::null(),
36    };
37
38    unsafe {
39        let mut raw = MaybeUninit::uninit();
40
41        let ret = lirc_readconfig_only(c_str, raw.as_mut_ptr(), None);
42        if ret == -1 {
43            return Err(-ret);
44        }
45
46        Ok(std::ptr::read(raw.assume_init()))
47    }
48}
49
50pub fn freeconfig(mut conf: lirc_config) {
51    unsafe {
52        lirc_freeconfig(&mut conf);
53    }
54}
55
56pub fn init(prog: &str, verbose: u32) -> Result<i32, std::io::Error> {
57    unsafe {
58        let prog_str = CString::new(prog).unwrap();
59        let ret = lirc_init(prog_str.as_ptr(), verbose);
60        if ret < 0 {
61            return Err(std::io::Error::last_os_error());
62        }
63
64        Ok(ret)
65    }
66}
67
68pub fn deinit() -> Result<(), std::io::Error> {
69    unsafe {
70        let ret = lirc_deinit();
71        if ret < 0 {
72            return Err(std::io::Error::last_os_error());
73        }
74
75        Ok(())
76    }
77}
78
79pub fn send_one(fd: i32, remote: &str, key: &str) -> Result<(), i32> {
80    let r = std::ffi::CString::new(remote).unwrap();
81    let k = std::ffi::CString::new(key).unwrap();
82
83    unsafe {
84        let ret = lirc_send_one(fd, r.as_ptr(), k.as_ptr());
85        if ret != 0 {
86            return Err(ret);
87        }
88
89        Ok(())
90    }
91}
92
93pub fn nextcode() -> Result<String, i32> {
94    unsafe {
95        let mut str_buf = MaybeUninit::uninit();
96        let ret = lirc_nextcode(str_buf.as_mut_ptr());
97        if ret != 0 {
98            return Err(ret);
99        }
100
101        let r = std::ffi::CStr::from_ptr(str_buf.assume_init()).to_str();
102        Ok(String::from(r.unwrap()))
103    }
104}
105
106pub fn code2char(mut conf: lirc_config, code: &mut str) -> Result<String, i32> {
107    unsafe {
108        let mut c = MaybeUninit::uninit();
109        let ret = lirc_code2char(&mut conf, code.as_mut_ptr(), c.as_mut_ptr());
110        if ret != 0 {
111            return Err(ret);
112        }
113
114        let a = std::ffi::CStr::from_ptr(c.assume_init() as *mut ::std::os::raw::c_char).to_str();
115        Ok(String::from(a.unwrap()))
116    }
117}
118
119pub fn get_local_socket(path: &str, quiet: bool) -> Result<i32, std::io::Error> {
120    let q = if quiet { 1 } else { 0 };
121    let p = std::ffi::CString::new(path).unwrap();
122
123    unsafe {
124        let r = lirc_get_local_socket(p.as_ptr(), q);
125        if r < 0 {
126            return Err(std::io::Error::last_os_error());
127        }
128
129        Ok(r)
130    }
131}
132
133pub fn get_remote_socket(host: &str, port: i32, quiet: bool) -> Result<i32, i32> {
134    unsafe {
135        let q: i32 = if quiet { 1 } else { 0 };
136        let h = std::ffi::CString::new(host).unwrap();
137        let r = lirc_get_remote_socket(h.as_ptr(), port, q);
138        if r < 0 {
139            return Err(r);
140        }
141
142        Ok(r)
143    }
144}
145
146pub fn set_mode(conf: &mut lirc_config, mode: &str) -> Result<String, std::io::Error> {
147    unsafe {
148        let m = std::ffi::CString::new(mode).expect("Failed to convert mode");
149
150        let ret = lirc_setmode(conf, m.as_ptr());
151        let ret_mode = CStr::from_ptr(ret);
152
153        if ret_mode.to_str().unwrap().eq(mode) {
154            return Err(std::io::Error::last_os_error());
155        }
156
157        Ok(ret_mode.to_str().unwrap().to_string())
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn test_init_deinit() {
167        let ret = init("Test", 1);
168        assert!(ret.is_ok(), "{:?}", ret.err());
169        assert!(ret.unwrap() > 0);
170
171        let ret = deinit();
172        assert!(ret.is_ok(), "{:?}", ret.err());
173
174        let ret = init("Test1", 10);
175        assert!(ret.is_ok(), "{:?}", ret.err());
176        assert!(ret.unwrap() > 0);
177
178        let ret = deinit();
179        assert!(ret.is_ok(), "{:?}", ret.err());
180    }
181}