rust_usbtmc/
instrument.rs1use crate::error::UsbtmcError;
2use crate::helper::UsbtmcResult;
3use byteorder::{ByteOrder, LittleEndian};
4use core::time::Duration;
5use rusb::Context;
6use rusb::Device;
7use rusb::DeviceDescriptor;
8use rusb::DeviceHandle;
9use rusb::Direction;
10use rusb::TransferType;
11use rusb::UsbContext;
12use std::str;
13
14const USBTMC_MSGID_DEV_DEP_MSG_OUT: u8 = 1;
15const USBTMC_MSGID_DEV_DEP_MSG_IN: u8 = 2;
16
17#[derive(Debug)]
18pub struct Endpoint {
19 pub config: u8,
20 pub iface: u8,
21 pub setting: u8,
22 pub address: u8,
23}
24
25pub struct Instrument {
26 pub vid: u16,
27 pub pid: u16,
28 last_btag: u8,
29 max_transfer_size: u32,
30 timeout: Duration,
31}
32
33impl Instrument {
34 pub fn new(vid: u16, pid: u16) -> Instrument {
38 Instrument {
39 vid,
40 pid,
41 last_btag: 0,
42 max_transfer_size: 1024 * 1024,
43 timeout: Duration::from_secs(1),
44 }
45 }
46
47 pub fn info(&self) -> UsbtmcResult<String> {
51 Ok(String::new())
52 }
53
54 pub fn write(&mut self, message: &str) -> UsbtmcResult<()> {
58 self.write_raw(message.as_bytes())
59 }
60
61 pub fn write_raw(&mut self, data: &[u8]) -> UsbtmcResult<()> {
65 self.write_data(data, false)
66 }
67
68 pub fn read(&mut self) -> UsbtmcResult<String> {
72 self.read_raw()
73 }
74
75 pub fn read_raw(&mut self) -> UsbtmcResult<String> {
79 let (mut device, device_desc, mut handle) = self.open_device()?;
80
81 match self.find_endpoint(&mut device, &device_desc, TransferType::Bulk, Direction::In) {
82 Some(endpoint) => {
83 let has_kernel_driver = match handle.kernel_driver_active(endpoint.iface) {
84 Ok(true) => {
85 handle.detach_kernel_driver(endpoint.iface).ok();
86 true
87 }
88 _ => false,
89 };
90
91 let buf = &mut [0u8; 1024];
92 handle.read_bulk(endpoint.address, buf, self.timeout)?;
93
94 let line_size = buf
95 .iter()
96 .take_while(|c| **c != b'\n' && **c != b'\r')
97 .count();
98
99 let result = str::from_utf8(&buf[12..line_size]).unwrap().to_string();
100
101 if has_kernel_driver {
102 handle.attach_kernel_driver(endpoint.iface).ok();
103 }
104
105 Ok(result)
106 }
107
108 None => return Err(UsbtmcError::BulkOut),
109 }
110 }
111
112 pub fn ask(&mut self, data: &str) -> UsbtmcResult<String> {
116 self.ask_raw(data.as_bytes())
117 }
118
119 pub fn ask_raw(&mut self, data: &[u8]) -> UsbtmcResult<String> {
123 self.write_data(data, true)?;
124 self.read_raw()
125 }
126
127 fn pack_bulk_out_header(&mut self, msgid: u8) -> Vec<u8> {
131 let btag: u8 = (self.last_btag % 255) + 1;
132 self.last_btag = btag;
133
134 vec![msgid, btag, !btag & 0xFF, 0x00]
136 }
137
138 fn pack_dev_dep_msg_out_header(&mut self, transfer_size: usize, eom: bool) -> Vec<u8> {
142 let mut hdr = self.pack_bulk_out_header(USBTMC_MSGID_DEV_DEP_MSG_OUT);
143
144 hdr.append(&mut self.little_write_u32(transfer_size as u32, 4));
145 hdr.push(if eom { 0x01 } else { 0x00 });
146 hdr.append(&mut vec![0x00; 3]);
147
148 hdr
149 }
150
151 fn pack_dev_dep_msg_in_header(&mut self, transfer_size: usize, term_char: u8) -> Vec<u8> {
155 let mut hdr = self.pack_bulk_out_header(USBTMC_MSGID_DEV_DEP_MSG_IN);
156
157 hdr.append(&mut self.little_write_u32(transfer_size as u32, 4));
158 hdr.push(if term_char == 0 { 0x00 } else { 0x02 });
159 hdr.push(term_char);
160 hdr.append(&mut vec![0x00; 2]);
161
162 hdr
163 }
164
165 fn little_write_u32(&self, size: u32, len: u8) -> Vec<u8> {
169 let mut buf = vec![0; len as usize];
170 LittleEndian::write_u32(&mut buf, size);
171
172 buf
173 }
174
175 fn open_device(
179 &self,
180 ) -> UsbtmcResult<(Device<Context>, DeviceDescriptor, DeviceHandle<Context>)> {
181 let context = Context::new().unwrap();
182 let devices = match context.devices() {
183 Ok(list) => list,
184 Err(_) => return Err(UsbtmcError::Exception),
185 };
186
187 for device in devices.iter() {
188 let device_desc = match device.device_descriptor() {
189 Ok(descriptor) => descriptor,
190 Err(_) => continue,
191 };
192
193 if device_desc.vendor_id() == self.vid && device_desc.product_id() == self.pid {
194 match device.open() {
195 Ok(handle) => return Ok((device, device_desc, handle)),
196 Err(_) => continue,
197 }
198 }
199 }
200
201 return Err(UsbtmcError::Exception);
202 }
203
204 fn find_endpoint(
208 &mut self,
209 device: &mut Device<Context>,
210 device_desc: &DeviceDescriptor,
211 transfer_type: TransferType,
212 direction: Direction,
213 ) -> Option<Endpoint> {
214 for index in 0..device_desc.num_configurations() {
215 let config_desc = match device.config_descriptor(index) {
216 Ok(c) => c,
217 Err(_) => continue,
218 };
219
220 for interface in config_desc.interfaces() {
221 for interface_desc in interface.descriptors() {
222 for endpoint_desc in interface_desc.endpoint_descriptors() {
223 if endpoint_desc.transfer_type() == transfer_type
224 && endpoint_desc.direction() == direction
225 {
226 return Some(Endpoint {
227 config: config_desc.number(),
228 iface: interface_desc.interface_number(),
229 setting: interface_desc.setting_number(),
230 address: endpoint_desc.address(),
231 });
232 }
233 }
234 }
235 }
236 }
237
238 None
239 }
240
241 fn write_data(&mut self, data: &[u8], command: bool) -> UsbtmcResult<()> {
245 let offset: usize = 0;
246 let mut eom: bool = false;
247 let mut num: usize = data.len();
248
249 let (mut device, device_desc, mut handle) = self.open_device()?;
250
251 match self.find_endpoint(
252 &mut device,
253 &device_desc,
254 TransferType::Bulk,
255 Direction::Out,
256 ) {
257 Some(endpoint) => {
258 let has_kernel_driver = match handle.kernel_driver_active(endpoint.iface) {
259 Ok(true) => {
260 handle.detach_kernel_driver(endpoint.iface).ok();
261 true
262 }
263 _ => false,
264 };
265
266 while num > 0 {
267 if num <= self.max_transfer_size as usize {
268 eom = true;
269 }
270
271 let block = &data[offset..(num - offset)];
272 let size: usize = block.len();
273
274 let mut req = self.pack_dev_dep_msg_out_header(size, eom);
275 let mut b: Vec<u8> = block.iter().cloned().collect();
276 req.append(&mut b);
277 req.append(&mut vec![0x00; (4 - (size % 4)) % 4]);
278
279 handle.write_bulk(endpoint.address, &req, self.timeout)?;
280
281 num = num - size;
282 }
283
284 if command {
285 let send = self.pack_dev_dep_msg_in_header(self.max_transfer_size as usize, 0);
286 handle.write_bulk(endpoint.address, &send, self.timeout)?;
287 }
288
289 if has_kernel_driver {
290 handle.attach_kernel_driver(endpoint.iface).ok();
291 }
292 }
293
294 None => return Err(UsbtmcError::BulkOut),
295 }
296
297 Ok(())
298 }
299}