1#![allow(clippy::upper_case_acronyms)]
44
45use parking_lot::RwLock;
46use pico_common::{
47 ChannelConfig, Driver, FromPicoStr, PicoChannel, PicoError, PicoInfo, PicoRange, PicoResult,
48 SampleConfig,
49};
50pub use resolution::LibraryResolution;
51use std::{fmt, sync::Arc};
52use thiserror::Error;
53use version_compare::Version;
54
55mod dependencies;
56pub mod kernel_driver;
57pub mod ps2000;
58pub mod ps2000a;
59pub mod ps3000a;
60pub mod ps4000;
61pub mod ps4000a;
62pub mod ps5000a;
63pub mod ps6000;
64pub mod ps6000a;
65pub mod psospa;
66mod resolution;
67mod trampoline;
68
69#[derive(Error, Debug)]
71pub enum DriverLoadError {
72 #[error("Pico driver error: {0}")]
73 DriverError(#[from] PicoError),
74
75 #[error("Library load error: {0}")]
76 LibloadingError(#[from] libloading::Error),
77
78 #[error("Invalid Driver Version: Requires >= {required}, Found: {found}")]
79 VersionError { found: String, required: String },
80}
81
82#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
84#[derive(Clone, Debug)]
85pub struct EnumerationResult {
86 pub variant: String,
87 pub serial: String,
88}
89
90pub trait PicoDriver: fmt::Debug + Send + Sync {
92 fn get_driver(&self) -> Driver;
94 fn get_version(&self) -> PicoResult<String>;
96 fn get_path(&self) -> PicoResult<Option<String>>;
98 fn enumerate_units(&self) -> PicoResult<Vec<EnumerationResult>>;
100 fn open_unit(&self, serial: Option<&str>) -> PicoResult<i16>;
102 fn ping_unit(&self, handle: i16) -> PicoResult<()>;
104 fn maximum_value(&self, handle: i16) -> PicoResult<i16>;
106 fn close(&self, handle: i16) -> PicoResult<()>;
108 fn get_unit_info(&self, handle: i16, info_type: PicoInfo) -> PicoResult<String>;
110 fn get_channel_ranges(&self, handle: i16, channel: PicoChannel) -> PicoResult<Vec<PicoRange>>;
112 fn enable_channel(
114 &self,
115 handle: i16,
116 channel: PicoChannel,
117 config: &ChannelConfig,
118 ) -> PicoResult<()>;
119 fn disable_channel(&self, handle: i16, channel: PicoChannel) -> PicoResult<()>;
121 fn set_data_buffer(
123 &self,
124 handle: i16,
125 channel: PicoChannel,
126 buffer: Arc<RwLock<Vec<i16>>>,
127 buffer_len: usize,
128 ) -> PicoResult<()>;
129 fn start_streaming(
131 &self,
132 handle: i16,
133 sample_config: &SampleConfig,
134 enabled_channels: u8,
135 ) -> PicoResult<SampleConfig>;
136 fn get_latest_streaming_values<'a>(
138 &self,
139 handle: i16,
140 channels: &[PicoChannel],
141 callback: Box<dyn FnMut(usize, usize) + 'a>,
142 ) -> PicoResult<()>;
143 fn stop(&self, handle: i16) -> PicoResult<()>;
145 fn check_version(&self) -> Result<(), DriverLoadError> {
147 let loaded_str = &self.get_version()?;
148 let loaded_version = Version::from(loaded_str);
149
150 let required_str = get_min_required_version(self.get_driver());
151 let required_version = Version::from(required_str);
152
153 if loaded_version < required_version {
154 Err(DriverLoadError::VersionError {
155 found: loaded_str.to_string(),
156 required: required_str.to_string(),
157 })
158 } else {
159 Ok(())
160 }
161 }
162}
163
164pub type ArcDriver = Arc<dyn PicoDriver>;
165
166pub(crate) fn get_version_string(input: &str) -> String {
167 input
168 .split(|s| s == ' ' || s == ',')
169 .last()
170 .expect("Invalid version string")
171 .to_string()
172}
173
174pub(crate) fn parse_enum_result(buffer: &[i8], len: usize) -> Vec<EnumerationResult> {
175 let serials_list = buffer.from_pico_i8_string(len);
176
177 serials_list
178 .split(',')
179 .map(String::from)
180 .map(|device| {
181 let parts = device.split('[').collect::<Vec<_>>();
182
183 EnumerationResult {
184 serial: parts[0].to_string(),
185 variant: parts[1].trim_end_matches(']').to_string(),
186 }
187 })
188 .collect()
189}
190
191fn get_min_required_version(driver: Driver) -> &'static str {
193 match driver {
194 Driver::PS2000 => "3.0.30.1878",
195 Driver::PS2000A
196 | Driver::PS3000A
197 | Driver::PS4000
198 | Driver::PS4000A
199 | Driver::PS5000A
200 | Driver::PS6000 => "2.1.30.1878",
201 Driver::PS6000A => "1.0.54.2438",
202 _ => panic!(
203 "We don't know the minimum required version for the {:?} driver!",
204 driver,
205 ),
206 }
207}