uem_reader/reader/
usb.rs

1//! USB reader implementation
2
3//use core::slice::SlicePattern;
4use std::sync::{Arc, Mutex};
5use std::{time::Duration};
6use rand::Rng;
7use rusb::{
8    DeviceHandle, DeviceList, Language, 
9    Device, UsbContext, Direction,
10};
11
12use crate::reader::*;
13use crate::reader::processing::*;
14use crate::errors::*;
15
16const UEM_VID: u16 = 0xC251;
17const UEM_PID: u16 = 0x130A;
18
19#[derive(Debug, Default)]
20struct ReaderUsb<T: UsbContext> {
21    handle: Option<DeviceHandle<T>>,
22    device: Option<Device<T>>,
23    language: Option<Language>,
24    timeout: Duration,
25    ep_in_addr: u8,
26    ep_out_addr: u8,
27    ncommand: u8,
28}
29
30impl<T: UsbContext> CommandsCounter for ReaderUsb<T> {
31    fn commands_count(&self) -> u8 {
32        self.ncommand
33    }
34
35    fn increment_commands(&mut self) {
36        if self.commands_count() == u8::MAX {
37            self.ncommand = 0;
38        }
39        self.ncommand += 1;
40    }
41}
42
43impl<T: UsbContext> UemReaderInternalTrait for ReaderUsb<T> {
44    //#![warn(missing_docs)]
45    /// Open USB interface
46    fn open(&mut self) -> UemResult {
47        if self.handle.is_some() {
48            return Err(UemError::ReaderAlreadyConnected);
49        }
50        if let Ok(h) = self.device.take().unwrap().open() {
51            if let Ok(l) = h.read_languages(TIMEOUT) {
52                if !l.is_empty() {
53                    self.language = Some(l[0]);
54                }
55            }
56            self.handle = Some(h);
57            self.timeout = TIMEOUT;
58            return Ok(())
59        }
60        Err(UemError::ReaderConnectionFailed)
61    }        
62
63    /// Close opened USB interface
64    fn close(&mut self) -> core::result::Result<(), UemError> {
65        if self.handle.is_none() {
66            return Err(UemError::ReaderNotConnected);
67        }
68        if let Some(h) = self.handle.take() {
69            self.device = Some(h.device());
70            return Ok(())
71        }
72        Ok(())
73    }
74
75    /// Send command directly to a USB reader
76    fn send(&mut self, command: &[u8]) -> UemResultVec {
77        
78        if self.handle.is_none() {
79            return Err(UemError::ReaderNotConnected);
80        }
81        if command.is_empty() {
82            return Err(UemError::IncorrectParameter);
83        }
84
85        let send_buffer = prepare_command(self, &command);
86        if send_buffer.is_empty() {
87            return Err(UemError::IncorrectParameter);
88        }
89
90        let handle = self.handle.as_mut().unwrap();
91
92        handle.claim_interface(0).map_err(|_| UemError::Access)?;
93
94        let mut res = handle.write_bulk(self.ep_out_addr, send_buffer.as_slice(), TIMEOUT);
95
96        if res.is_err() {
97            return Err(UemError::NotTransacted);
98        }
99
100        let mut receive_buffer = vec![0u8; 256];
101
102        res = handle.read_bulk(self.ep_in_addr, &mut receive_buffer, TIMEOUT);
103
104        handle.release_interface(0).map_err(|_| UemError::Access)?;
105
106        if res.is_err() {
107            return Err(UemError::ReaderResponseFailure);
108        }
109
110        let response_length = res.unwrap();
111
112        if response_length <= 6 {
113            return Err(UemError::ReaderResponseFailure);
114        }
115
116        let response = parse_response(&receive_buffer[..response_length].to_vec())?;
117
118        if (response.len() < 2) || (response[0] != command[0]) {
119            return Err(UemError::ReaderIncorrectResponse);
120        }
121
122        if response[1] != 0x00 {
123            if response.len() == 2 {
124                return Err(UemError::ReaderUnsuccessful(UemInternalError::from_byte(response[1]), None));
125            }
126            return Err(UemError::ReaderUnsuccessful(UemInternalError::from_byte(response[1]), Some(response[2..].to_vec())));
127        }
128
129        Ok(response[2..].to_vec())
130    }
131}
132
133/// Search system for MicroEM readers on USB ports
134/// 
135/// # Example
136/// 
137/// ```no_run
138/// # use uem_reader::reader::*;
139/// # use uem_reader::reader::usb::find_usb_readers;
140/// 
141/// // Search system for USB readers
142/// let mut uem_readers = find_usb_readers();
143/// 
144/// // Quit if no readers found
145/// if uem_readers.is_empty() {
146///     return;
147/// }
148/// 
149/// // Pick the first reader in the vector
150/// let uem_reader = uem_readers.get_mut(0);
151/// 
152/// // Check if the vector returned an option with valid reader object
153/// if uem_reader.is_none() {
154///     return;
155/// }
156/// 
157/// // Unwrap the option
158/// let uem_reader = uem_reader.unwrap();
159/// ```
160pub fn find_usb_readers() -> Vec<UemReader> {
161    let mut usb_readers: Vec<UemReader> = Vec::new();
162    let devices = DeviceList::new();
163    if let Err(_) = devices {
164        return usb_readers;
165    }
166    for device in devices.unwrap().iter() {
167        let device_desc = match device.device_descriptor() {
168            Ok(d) => d,
169            Err(_) => continue,
170        };
171
172        if  device_desc.vendor_id() != UEM_VID || 
173            device_desc.product_id() != UEM_PID {
174            continue
175        }
176
177        let mut usb_reader = ReaderUsb {
178            ncommand: rand::thread_rng().gen(),
179            ..Default::default()
180        };
181
182        for n in 0..device_desc.num_configurations() {
183            let config_desc = match device.config_descriptor(n) {
184                Ok(c) => c,
185                Err(_) => continue,
186            };
187
188            for interface in config_desc.interfaces() {
189                for interface_desc in interface.descriptors() {
190                    for endpoint_desc in interface_desc.endpoint_descriptors() {
191                        match endpoint_desc.direction() {
192                            Direction::In => usb_reader.ep_in_addr = endpoint_desc.address(),
193                            Direction::Out => usb_reader.ep_out_addr = endpoint_desc.address()
194                        }
195                    }
196                }
197            }
198        }
199        usb_reader.device = Some(device);
200        usb_readers.push(Arc::new(Mutex::new(usb_reader)));
201    }
202
203    usb_readers
204}