1use crate::{check, ffi, Result};
2use std::os::raw::{c_char, c_int, c_uint};
3
4pub(crate) type Handle = std::os::raw::c_long;
8
9const MAX_DEVS: usize = ffi::NEORADIO2_MAX_DEVS as usize;
10
11fn cstr_to_string(buf: &[c_char]) -> String {
12 let bytes: Vec<u8> = buf
13 .iter()
14 .take_while(|&&c| c != 0)
15 .map(|&c| c as u8)
16 .collect();
17 String::from_utf8_lossy(&bytes).into_owned()
18}
19
20#[derive(Clone)]
22pub struct DeviceInfo(pub(crate) ffi::Neoradio2DeviceInfo);
23
24impl DeviceInfo {
25 pub fn name(&self) -> String {
27 cstr_to_string(&self.0.name)
28 }
29 pub fn serial(&self) -> String {
31 cstr_to_string(&self.0.serial_str)
32 }
33 pub fn vendor_id(&self) -> i32 {
35 self.0.vendor_id
36 }
37 pub fn product_id(&self) -> i32 {
39 self.0.product_id
40 }
41}
42
43impl std::fmt::Debug for DeviceInfo {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 f.debug_struct("DeviceInfo")
46 .field("name", &self.name())
47 .field("serial", &self.serial())
48 .field("vendor_id", &format_args!("{:#06x}", self.vendor_id()))
49 .field("product_id", &format_args!("{:#06x}", self.product_id()))
50 .finish()
51 }
52}
53
54pub struct Device {
61 pub(crate) handle: Handle,
62 _not_sync: std::marker::PhantomData<*const ()>,
67}
68
69unsafe impl Send for Device {}
71
72impl Device {
73 pub fn find() -> Result<Vec<DeviceInfo>> {
75 let mut buf: [ffi::Neoradio2DeviceInfo; MAX_DEVS] = unsafe { std::mem::zeroed() };
76 let mut count: c_uint = MAX_DEVS as c_uint;
77 check(unsafe { ffi::neoradio2_find(buf.as_mut_ptr(), &mut count) })?;
78 let n = (count as usize).min(MAX_DEVS);
79 Ok(buf[..n].iter().map(|raw| DeviceInfo(*raw)).collect())
80 }
81
82 pub fn open(info: &DeviceInfo) -> Result<Device> {
84 let mut raw = info.0;
85 let mut handle: Handle = -1;
86 check(unsafe { ffi::neoradio2_open(&mut handle, &mut raw) })?;
87 Ok(Device {
88 handle,
89 _not_sync: std::marker::PhantomData,
90 })
91 }
92
93 pub fn is_opened(&self) -> Result<bool> {
95 let mut out: c_int = 0;
96 let mut h = self.handle;
97 check(unsafe { ffi::neoradio2_is_opened(&mut h, &mut out) })?;
98 Ok(out != 0)
99 }
100
101 pub fn is_closed(&self) -> Result<bool> {
103 let mut out: c_int = 0;
104 let mut h = self.handle;
105 check(unsafe { ffi::neoradio2_is_closed(&mut h, &mut out) })?;
106 Ok(out != 0)
107 }
108}
109
110impl Device {
111 pub fn chain_identify(&self) -> Result<()> {
113 let mut h = self.handle;
114 check(unsafe { ffi::neoradio2_chain_identify(&mut h) })
115 }
116
117 pub fn chain_is_identified(&self) -> Result<bool> {
119 let mut out: c_int = 0;
120 let mut h = self.handle;
121 check(unsafe { ffi::neoradio2_chain_is_identified(&mut h, &mut out) })?;
122 Ok(out != 0)
123 }
124
125 pub fn chain_count(&self, identify: bool) -> Result<i32> {
127 let mut out: c_int = 0;
128 let mut h = self.handle;
129 check(unsafe { ffi::neoradio2_get_chain_count(&mut h, &mut out, identify as c_int) })?;
130 Ok(out)
131 }
132
133 pub fn app_start(&self, device: i32, bank: i32) -> Result<()> {
135 let mut h = self.handle;
136 check(unsafe { ffi::neoradio2_app_start(&mut h, device, bank) })
137 }
138
139 pub fn app_is_started(&self, device: i32, bank: i32) -> Result<bool> {
141 let mut out: c_int = 0;
142 let mut h = self.handle;
143 check(unsafe { ffi::neoradio2_app_is_started(&mut h, device, bank, &mut out) })?;
144 Ok(out != 0)
145 }
146
147 pub fn enter_bootloader(&self, device: i32, bank: i32) -> Result<()> {
149 let mut h = self.handle;
150 check(unsafe { ffi::neoradio2_enter_bootloader(&mut h, device, bank) })
151 }
152}
153
154impl Device {
155 pub fn serial_number(&self, device: i32, bank: i32) -> Result<u32> {
157 let mut out: c_uint = 0;
158 let mut h = self.handle;
159 check(unsafe { ffi::neoradio2_get_serial_number(&mut h, device, bank, &mut out) })?;
160 Ok(out)
161 }
162
163 pub fn manufacturer_date(&self, device: i32, bank: i32) -> Result<(i32, i32, i32)> {
165 let (mut y, mut m, mut d) = (0, 0, 0);
166 let mut h = self.handle;
167 check(unsafe {
168 ffi::neoradio2_get_manufacturer_date(&mut h, device, bank, &mut y, &mut m, &mut d)
169 })?;
170 Ok((y, m, d))
171 }
172
173 pub fn firmware_version(&self, device: i32, bank: i32) -> Result<(i32, i32)> {
175 let (mut major, mut minor) = (0, 0);
176 let mut h = self.handle;
177 check(unsafe {
178 ffi::neoradio2_get_firmware_version(&mut h, device, bank, &mut major, &mut minor)
179 })?;
180 Ok((major, minor))
181 }
182
183 pub fn hardware_revision(&self, device: i32, bank: i32) -> Result<(i32, i32)> {
185 let (mut major, mut minor) = (0, 0);
186 let mut h = self.handle;
187 check(unsafe {
188 ffi::neoradio2_get_hardware_revision(&mut h, device, bank, &mut major, &mut minor)
189 })?;
190 Ok((major, minor))
191 }
192
193 pub fn device_type(&self, device: i32, bank: i32) -> Result<u32> {
195 let mut out: c_uint = 0;
196 let mut h = self.handle;
197 check(unsafe { ffi::neoradio2_get_device_type(&mut h, device, bank, &mut out) })?;
198 Ok(out)
199 }
200
201 pub fn request_pcbsn(&self, device: i32, bank: i32) -> Result<()> {
203 let mut h = self.handle;
204 check(unsafe { ffi::neoradio2_request_pcbsn(&mut h, device, bank) })
205 }
206
207 pub fn pcbsn(&self, device: i32, bank: i32) -> Result<String> {
209 let mut buf = [0 as c_char; 17];
210 let mut h = self.handle;
211 check(unsafe { ffi::neoradio2_get_pcbsn(&mut h, device, bank, buf.as_mut_ptr()) })?;
212 Ok(cstr_to_string(&buf))
213 }
214}
215
216use crate::CalType;
217
218impl Device {
219 pub fn request_sensor_data(&self, device: i32, bank: i32, cal: CalType) -> Result<()> {
221 let mut h = self.handle;
222 check(unsafe { ffi::neoradio2_request_sensor_data(&mut h, device, bank, cal.as_raw()) })
223 }
224
225 pub fn read_sensor_float(&self, device: i32, bank: i32) -> Result<f32> {
227 let mut out: f32 = 0.0;
228 let mut h = self.handle;
229 check(unsafe { ffi::neoradio2_read_sensor_float(&mut h, device, bank, &mut out) })?;
230 Ok(out)
231 }
232
233 pub fn read_sensor_array(&self, device: i32, bank: i32) -> Result<Vec<i32>> {
235 let mut arr = [0 as c_int; 64];
236 let mut len: c_int = arr.len() as c_int;
237 let mut h = self.handle;
238 check(unsafe {
239 ffi::neoradio2_read_sensor_array(&mut h, device, bank, arr.as_mut_ptr(), &mut len)
240 })?;
241 let n = (len.max(0) as usize).min(arr.len());
242 Ok(arr[..n].to_vec())
243 }
244
245 pub fn write_sensor(&self, device: i32, bank: i32, data: &[u8]) -> Result<()> {
247 let mut h = self.handle;
248 check(unsafe {
249 ffi::neoradio2_write_sensor(
250 &mut h,
251 device,
252 bank,
253 data.as_ptr() as *mut u8,
254 data.len() as c_int,
255 )
256 })
257 }
258
259 pub fn write_sensor_successful(&self, device: i32, bank: i32) -> Result<()> {
261 let mut h = self.handle;
262 check(unsafe { ffi::neoradio2_write_sensor_successful(&mut h, device, bank) })
263 }
264}
265
266impl Drop for Device {
267 fn drop(&mut self) {
268 unsafe { ffi::neoradio2_close(&mut self.handle) };
269 }
270}