linux_gpib_rs/
asynchronous.rs

1use crate::error::{GpibError, IbError};
2use crate::status::IbStatus;
3use std::os::raw::{c_int, c_void};
4
5pub async fn wait(ud: c_int, status_mask: IbStatus) -> Result<IbStatus, GpibError> {
6    let status_mask = status_mask.as_ibsta();
7    let status = IbStatus::from_ibsta(
8        tokio::task::spawn_blocking(move || unsafe { linux_gpib_sys::ibwait(ud, status_mask) })
9            .await?,
10    );
11    if status.err {
12        Err(GpibError::DriverError(status, IbError::current_error()?))
13    } else {
14        Ok(status)
15    }
16}
17
18pub async fn read(ud: c_int) -> Result<String, GpibError> {
19    const BUFFER_SIZE: usize = 1024;
20    let mut result: Vec<u8> = Vec::new();
21    loop {
22        let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
23        let status = IbStatus::from_ibsta(unsafe {
24            linux_gpib_sys::ibrda(
25                ud,
26                buffer.as_mut_ptr() as *mut c_void,
27                buffer.len().try_into()?,
28            )
29        });
30        if status.err {
31            return Err(GpibError::DriverError(status, IbError::current_error()?));
32        }
33        let status = wait(
34            ud,
35            IbStatus::default()
36                .with_timo(true)
37                .with_cmpl(true)
38                .with_end(true),
39        )
40        .await?;
41        if status.timo {
42            return Err(GpibError::Timeout);
43        }
44        let n_read: usize = unsafe { linux_gpib_sys::ibcntl }.try_into()?;
45        if n_read > 0 {
46            result.extend(buffer[0..n_read].to_vec());
47        }
48        if status.end || n_read < BUFFER_SIZE || n_read == 0 {
49            break;
50        }
51    }
52    let answer = String::from_utf8(result)?;
53    Ok(answer)
54}
55
56pub async fn write(ud: c_int, data: &str) -> Result<(), GpibError> {
57    let data = data.as_bytes();
58    let status = IbStatus::from_ibsta(unsafe {
59        linux_gpib_sys::ibwrta(ud, data.as_ptr() as *const c_void, data.len().try_into()?)
60    });
61    if status.err {
62        return Err(GpibError::DriverError(status, IbError::current_error()?));
63    }
64    let status = wait(
65        ud,
66        IbStatus::default()
67            .with_timo(true)
68            .with_cmpl(true)
69            .with_end(true)
70            .with_rqs(true),
71    )
72    .await?;
73    if status.timo {
74        Err(GpibError::Timeout)
75    } else if status.cmpl || status.end {
76        Ok(())
77    } else {
78        Err(GpibError::ValueError(format!(
79            "Unexpected status after waiting: {:?}",
80            status
81        )))
82    }
83}