rust_usbtmc/
instrument.rs

1use 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    ///
35    ///
36    ///
37    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    ///
48    ///
49    ///
50    pub fn info(&self) -> UsbtmcResult<String> {
51        Ok(String::new())
52    }
53
54    ///
55    ///
56    ///
57    pub fn write(&mut self, message: &str) -> UsbtmcResult<()> {
58        self.write_raw(message.as_bytes())
59    }
60
61    ///
62    ///
63    ///
64    pub fn write_raw(&mut self, data: &[u8]) -> UsbtmcResult<()> {
65        self.write_data(data, false)
66    }
67
68    ///
69    ///
70    ///
71    pub fn read(&mut self) -> UsbtmcResult<String> {
72        self.read_raw()
73    }
74
75    ///
76    ///
77    ///
78    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    ///
113    ///
114    ///
115    pub fn ask(&mut self, data: &str) -> UsbtmcResult<String> {
116        self.ask_raw(data.as_bytes())
117    }
118
119    ///
120    ///
121    ///
122    pub fn ask_raw(&mut self, data: &[u8]) -> UsbtmcResult<String> {
123        self.write_data(data, true)?;
124        self.read_raw()
125    }
126
127    ///
128    ///
129    ///
130    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        // BBBx
135        vec![msgid, btag, !btag & 0xFF, 0x00]
136    }
137
138    ///
139    ///
140    ///
141    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    ///
152    ///
153    ///
154    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    ///
166    ///
167    ///
168    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    ///
176    ///
177    ///
178    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    ///
205    ///
206    ///
207    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    ///
242    ///
243    ///
244    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}