1use crate::config::Config;
2use crate::constants;
3use crate::error::{Error, Result};
4use crate::usb::{Endpoint, UsbDevice};
5use std::time::{Duration, Instant};
6
7const SYNC_TIMEOUT: Duration = Duration::from_secs(1);
8
9pub struct Device {
15 usb: UsbDevice,
16 config: Config,
17 encryption: EncryptionState,
18}
19
20impl Device {
21 pub fn new() -> Result<Self> {
22 Ok(Self {
23 usb: UsbDevice::new()?,
24 config: Config::new(),
25 encryption: EncryptionState::default(),
26 })
27 }
28
29 pub fn connect() -> Result<Self> {
30 let mut device = Self::new()?;
31 device.open()?;
32 device.initialize()?;
33 Ok(device)
34 }
35
36 pub fn usb(&self) -> &UsbDevice {
37 &self.usb
38 }
39
40 pub fn config(&self) -> &Config {
41 &self.config
42 }
43
44 pub fn config_mut(&mut self) -> &mut Config {
45 &mut self.config
46 }
47
48 pub fn is_open(&self) -> bool {
49 self.usb.is_open()
50 }
51
52 pub fn open(&mut self) -> Result<()> {
53 self.usb.open(constants::DW_VID, constants::DW_PID)
54 }
55
56 pub fn close(&mut self) -> Result<()> {
57 self.usb.close()
58 }
59
60 pub fn initialize(&mut self) -> Result<()> {
61 self.read_encrypt_table()?;
62 self.encryption.decode_table();
63 self.read_config()?;
64 Ok(())
65 }
66
67 pub fn reset_engine(&self) -> Result<()> {
68 self.usb.write_bytes(Endpoint::Command, &[0x02])
69 }
70
71 pub fn ensure_session(&mut self) -> Result<()> {
72 if !self.is_open() {
73 self.open()?;
74 }
75 self.initialize()
76 }
77
78 pub fn enter_io_mode(&mut self, settings: &IoSettings) -> Result<()> {
79 self.ensure_session()?;
80
81 let actual_version = self.config.smims_version_raw();
82 if actual_version < constants::SMIMS_VERSION {
83 return Err(Error::VersionMismatch {
84 expected: constants::SMIMS_VERSION,
85 actual: actual_version,
86 });
87 }
88
89 if !self.config.is_programmed() {
90 return Err(Error::NotProgrammed);
91 }
92
93 if !self.config.vericomm_ability() {
94 return Err(Error::FeatureUnavailable("vericomm"));
95 }
96
97 if let Some(licence_key) = settings.licence_key {
98 self.config.set_licence_key(licence_key);
99 }
100
101 self.config
102 .set_vericomm_clock_high_delay(settings.clock_high_delay);
103 self.config
104 .set_vericomm_clock_low_delay(settings.clock_low_delay);
105 self.config.set_vericomm_isv(settings.vericomm_isv);
106 self.config
107 .set_vericomm_clock_check_enabled(settings.clock_check_enabled);
108 self.config.set_mode_selector(settings.mode_selector);
109
110 self.write_config()?;
111 self.activate_vericomm()?;
112 Ok(())
113 }
114
115 pub fn transfer_io(&mut self, write_buffer: &mut [u16], read_buffer: &mut [u16]) -> Result<()> {
116 self.encrypt(write_buffer);
117 self.fifo_write(write_buffer)?;
118 self.fifo_read(read_buffer)?;
119 self.decrypt(read_buffer);
120 Ok(())
121 }
122
123 pub fn exit_io_mode(&mut self) -> Result<()> {
124 if !self.is_open() {
125 return Ok(());
126 }
127
128 self.command_active()?;
129 self.close()
130 }
131
132 pub fn fifo_write(&self, buffer: &[u16]) -> Result<()> {
133 self.usb.write_words(Endpoint::FifoWrite, buffer)
134 }
135
136 pub fn fifo_read(&self, buffer: &mut [u16]) -> Result<()> {
137 self.usb.read_words(Endpoint::FifoRead, buffer)
138 }
139
140 pub fn sync_delay(&self) -> Result<()> {
141 let start = Instant::now();
142 let mut buffer = [0u8; 1];
143
144 while start.elapsed() <= SYNC_TIMEOUT {
145 self.usb.write_bytes(Endpoint::Command, &buffer)?;
146 self.usb.read_bytes(Endpoint::Sync, &mut buffer)?;
147 if buffer[0] != 0 {
148 return Ok(());
149 }
150 }
151
152 Err(Error::Timeout("sync_delay"))
153 }
154
155 pub fn command_active(&self) -> Result<()> {
156 self.sync_delay()?;
157 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x00])
158 }
159
160 pub fn read_config(&mut self) -> Result<()> {
161 self.sync_delay()?;
162 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x01])?;
163
164 let mut words = [0u16; Config::WORD_COUNT];
165 self.usb.read_words(Endpoint::FifoRead, &mut words)?;
166 self.command_active()?;
167 self.decrypt(&mut words);
168 self.config = Config::from_words(words);
169 Ok(())
170 }
171
172 pub fn write_config(&mut self) -> Result<()> {
173 self.sync_delay()?;
174 let mut words = *self.config.words();
175 self.encrypt(&mut words);
176 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x11])?;
177 self.usb.write_words(Endpoint::FifoWrite, &words)?;
178 self.command_active()
179 }
180
181 pub fn activate_fpga_programmer(&self) -> Result<()> {
182 self.sync_delay()?;
183 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x02])
184 }
185
186 pub fn activate_vericomm(&self) -> Result<()> {
187 self.sync_delay()?;
188 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x03])
189 }
190
191 pub fn activate_veri_instrument(&self) -> Result<()> {
192 self.sync_delay()?;
193 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x08])
194 }
195
196 pub fn activate_verilink(&self) -> Result<()> {
197 self.sync_delay()?;
198 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x09])
199 }
200
201 pub fn activate_veri_soc(&self) -> Result<()> {
202 self.sync_delay()?;
203 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x0a])
204 }
205
206 pub fn activate_vericomm_pro(&self) -> Result<()> {
207 self.sync_delay()?;
208 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x0b])
209 }
210
211 pub fn activate_veri_sdk(&self) -> Result<()> {
212 self.sync_delay()?;
213 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x04])
214 }
215
216 pub fn activate_flash_read(&self) -> Result<()> {
217 self.sync_delay()?;
218 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x05])
219 }
220
221 pub fn activate_flash_write(&self) -> Result<()> {
222 self.sync_delay()?;
223 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x15])
224 }
225
226 pub fn encrypt(&mut self, buffer: &mut [u16]) {
227 self.encryption.encrypt_words(buffer);
228 }
229
230 pub fn decrypt(&mut self, buffer: &mut [u16]) {
231 self.encryption.decrypt_words(buffer);
232 }
233
234 pub fn licence_gen(&self, security_key: u16, customer_id: u16) -> u16 {
235 licence_gen(security_key, customer_id)
236 }
237
238 fn read_encrypt_table(&mut self) -> Result<()> {
239 self.sync_delay()?;
240 self.usb.write_bytes(Endpoint::Command, &[0x01, 0x0f])?;
241 self.usb
242 .read_words(Endpoint::FifoRead, self.encryption.table_mut())
243 }
244}
245
246#[derive(Debug, Clone, Default)]
247struct EncryptionState {
248 table: [u16; 32],
249 encode_index: usize,
250 decode_index: usize,
251}
252
253impl EncryptionState {
254 fn table_mut(&mut self) -> &mut [u16; 32] {
255 &mut self.table
256 }
257
258 fn decode_table(&mut self) {
259 if self.table.is_empty() {
260 return;
261 }
262 self.table[0] = !self.table[0];
263 for idx in 1..self.table.len() {
264 let prev = self.table[idx - 1];
265 self.table[idx] ^= prev;
266 }
267 self.reset_indices();
268 }
269
270 fn encrypt_words(&mut self, buffer: &mut [u16]) {
271 let key = &self.table[0..16];
272 let mut index = self.encode_index;
273 for word in buffer.iter_mut() {
274 *word ^= key[index];
275 index = (index + 1) & 0x0f;
276 }
277 self.encode_index = index;
278 }
279
280 fn decrypt_words(&mut self, buffer: &mut [u16]) {
281 let key = &self.table[16..32];
282 let mut index = self.decode_index;
283 for word in buffer.iter_mut() {
284 *word ^= key[index];
285 index = (index + 1) & 0x0f;
286 }
287 self.decode_index = index;
288 }
289
290 fn reset_indices(&mut self) {
291 self.encode_index = 0;
292 self.decode_index = 0;
293 }
294}
295
296#[derive(Debug, Clone)]
299pub struct IoSettings {
300 pub clock_high_delay: u16,
301 pub clock_low_delay: u16,
302 pub vericomm_isv: u8,
303 pub clock_check_enabled: bool,
304 pub mode_selector: u8,
305 pub licence_key: Option<u16>,
306}
307
308impl Default for IoSettings {
309 fn default() -> Self {
310 Self {
311 clock_high_delay: 11,
312 clock_low_delay: 11,
313 vericomm_isv: 0,
314 clock_check_enabled: false,
315 mode_selector: 0,
316 licence_key: Some(0xff40),
317 }
318 }
319}
320
321fn licence_gen(security_key: u16, customer_id: u16) -> u16 {
322 let mut temp: u32 = 0;
323
324 let mut i: u16 = security_key & 0x0003;
325 let mut j: u16 = (customer_id & 0x000f) << 4;
326 j >>= i;
327 j = (j >> 4) | (j & 0x000f);
328 temp |= (j as u32) << 16;
329
330 i = (security_key & 0x0030) >> 4;
331 j = customer_id & 0x00f0;
332 j >>= i;
333 j = (j >> 4) | (j & 0x000f);
334 temp |= (j as u32) << 20;
335
336 i = (security_key & 0x0300) >> 8;
337 j = (customer_id & 0x0f00) >> 4;
338 j >>= i;
339 j = (j >> 4) | (j & 0x000f);
340 temp |= (j as u32) << 24;
341
342 i = (security_key & 0x3000) >> 12;
343 j = (customer_id & 0xf000) >> 8;
344 j >>= i;
345 j = (j >> 4) | (j & 0x000f);
346 temp |= (j as u32) << 28;
347
348 temp >>= 11;
349 !((temp >> 16) | (temp & 0x0000ffff)) as u16
350}