Skip to main content

instrument_visa/
enumerator.rs

1use crate::error::map_visa_error;
2use crate::rm::SharedRm;
3use crate::transport::read_identity_from_instrument;
4use instrument_core::address::{InterfaceKind, ResourceAddress};
5use instrument_core::enumerator::{RawResource, ResourceEnumerator};
6use instrument_core::Result;
7use std::ffi::CString;
8use visa_rs::enums::attribute::AttrIntfType;
9use visa_rs::prelude::{AccessMode, AsResourceManager, TIMEOUT_IMMEDIATE};
10
11/// VISA-backed resource enumerator.
12pub struct VisaEnumerator {
13    rm: SharedRm,
14}
15
16impl VisaEnumerator {
17    pub fn new(rm: SharedRm) -> Self {
18        Self { rm }
19    }
20
21    fn intf_type_to_kind(intf: AttrIntfType) -> InterfaceKind {
22        if intf == AttrIntfType::VI_INTF_GPIB {
23            InterfaceKind::Gpib
24        } else if intf == AttrIntfType::VI_INTF_VXI || intf == AttrIntfType::VI_INTF_GPIB_VXI {
25            InterfaceKind::Vxi
26        } else if intf == AttrIntfType::VI_INTF_ASRL {
27            InterfaceKind::Serial
28        } else if intf == AttrIntfType::VI_INTF_TCPIP {
29            InterfaceKind::Tcpip
30        } else if intf == AttrIntfType::VI_INTF_USB {
31            InterfaceKind::Usb
32        } else if intf == AttrIntfType::VI_INTF_PXI {
33            InterfaceKind::Pxi
34        } else {
35            InterfaceKind::Unknown
36        }
37    }
38}
39
40impl ResourceEnumerator for VisaEnumerator {
41    fn list(&self, pattern: &str) -> Result<Vec<RawResource>> {
42        let expr = CString::new(pattern)
43            .map_err(|e| instrument_core::Error::Parse(e.to_string()))?
44            .into();
45        let list = self
46            .rm
47            .strong()
48            .find_res_list(&expr)
49            .map_err(map_visa_error)?;
50
51        let mut resources = Vec::new();
52        for res_id in list {
53            let res_id = res_id.map_err(map_visa_error)?;
54            let raw = res_id.to_string();
55            let mut address = ResourceAddress::parse(&raw)?;
56            if let Ok((intf, _)) = self.rm.strong().parse_res(&res_id) {
57                address.interface = VisaEnumerator::intf_type_to_kind(intf);
58            }
59
60            let mut identity_hint = instrument_core::transport::TransportIdentity {
61                interface: address.interface,
62                ..Default::default()
63            };
64
65            if let Ok(instr) =
66                self.rm
67                    .strong()
68                    .open(&res_id, AccessMode::NO_LOCK, TIMEOUT_IMMEDIATE)
69            {
70                identity_hint = read_identity_from_instrument(&instr);
71                identity_hint.interface = address.interface;
72            }
73
74            resources.push(RawResource {
75                address,
76                identity_hint,
77            });
78        }
79        Ok(resources)
80    }
81}