1use bytes::Buf;
17
18use crate::U3vError;
19use crate::control::ControlChannel;
20use crate::usb::UsbTransfer;
21
22mod abrm_reg {
28 pub const GENCP_VERSION: u64 = 0x0000;
29 pub const MANUFACTURER_NAME: u64 = 0x0048;
30 pub const MODEL_NAME: u64 = 0x0088;
31 pub const FAMILY_NAME: u64 = 0x00C8;
32 pub const DEVICE_VERSION: u64 = 0x0108;
33 pub const SERIAL_NUMBER: u64 = 0x01A8;
34 pub const USER_DEFINED_NAME: u64 = 0x01E8;
35 pub const MANIFEST_TABLE_ADDR: u64 = 0x0228;
36 pub const SBRM_ADDRESS: u64 = 0x0230;
37 pub const DEVICE_CAPABILITY: u64 = 0x0238;
38
39 pub const STRING_LEN: usize = 64;
41}
42
43#[derive(Debug, Clone)]
45pub struct Abrm {
46 pub gencp_version: u32,
47 pub manufacturer_name: String,
48 pub model_name: String,
49 pub family_name: String,
50 pub device_version: String,
51 pub serial_number: String,
52 pub user_defined_name: String,
53 pub manifest_table_address: u64,
54 pub sbrm_address: u64,
55 pub device_capability: u64,
56}
57
58impl Abrm {
59 pub fn read_from<T: UsbTransfer>(control: &mut ControlChannel<T>) -> Result<Self, U3vError> {
61 let read_string = |ctrl: &mut ControlChannel<T>, addr: u64| -> Result<String, U3vError> {
62 let raw = ctrl.read_mem(addr, abrm_reg::STRING_LEN)?;
63 Ok(parse_nul_string(&raw))
64 };
65
66 let gencp_ver_bytes = control.read_mem(abrm_reg::GENCP_VERSION, 4)?;
67 let gencp_version = read_u32_be(&gencp_ver_bytes);
68
69 let manufacturer_name = read_string(control, abrm_reg::MANUFACTURER_NAME)?;
70 let model_name = read_string(control, abrm_reg::MODEL_NAME)?;
71 let family_name = read_string(control, abrm_reg::FAMILY_NAME)?;
72 let device_version = read_string(control, abrm_reg::DEVICE_VERSION)?;
73 let serial_number = read_string(control, abrm_reg::SERIAL_NUMBER)?;
74 let user_defined_name = read_string(control, abrm_reg::USER_DEFINED_NAME)?;
75
76 let manifest_bytes = control.read_mem(abrm_reg::MANIFEST_TABLE_ADDR, 8)?;
77 let manifest_table_address = read_u64_be(&manifest_bytes);
78
79 let sbrm_bytes = control.read_mem(abrm_reg::SBRM_ADDRESS, 8)?;
80 let sbrm_address = read_u64_be(&sbrm_bytes);
81
82 let cap_bytes = control.read_mem(abrm_reg::DEVICE_CAPABILITY, 8)?;
83 let device_capability = read_u64_be(&cap_bytes);
84
85 Ok(Self {
86 gencp_version,
87 manufacturer_name,
88 model_name,
89 family_name,
90 device_version,
91 serial_number,
92 user_defined_name,
93 manifest_table_address,
94 sbrm_address,
95 device_capability,
96 })
97 }
98}
99
100mod sbrm_reg {
106 pub const U3V_VERSION: u64 = 0x0000;
107 pub const MAX_CMD_TRANSFER: u64 = 0x0004;
108 pub const MAX_ACK_TRANSFER: u64 = 0x0008;
109 pub const NUM_STREAM_CHANNELS: u64 = 0x000C;
110 pub const SIRM_ADDRESS: u64 = 0x0010;
111 pub const SIRM_LENGTH: u64 = 0x0018;
112 pub const EIRM_ADDRESS: u64 = 0x001C;
113 pub const EIRM_LENGTH: u64 = 0x0024;
114}
115
116#[derive(Debug, Clone)]
118pub struct Sbrm {
119 pub base: u64,
120 pub u3v_version: u32,
121 pub max_cmd_transfer: u32,
122 pub max_ack_transfer: u32,
123 pub num_stream_channels: u32,
124 pub sirm_address: u64,
125 pub sirm_length: u32,
126 pub eirm_address: u64,
127 pub eirm_length: u32,
128}
129
130impl Sbrm {
131 pub fn read_from<T: UsbTransfer>(
133 control: &mut ControlChannel<T>,
134 base: u64,
135 ) -> Result<Self, U3vError> {
136 let read_u32 = |ctrl: &mut ControlChannel<T>, off: u64| -> Result<u32, U3vError> {
137 let bytes = ctrl.read_mem(base + off, 4)?;
138 Ok(read_u32_be(&bytes))
139 };
140 let read_u64 = |ctrl: &mut ControlChannel<T>, off: u64| -> Result<u64, U3vError> {
141 let bytes = ctrl.read_mem(base + off, 8)?;
142 Ok(read_u64_be(&bytes))
143 };
144
145 Ok(Self {
146 base,
147 u3v_version: read_u32(control, sbrm_reg::U3V_VERSION)?,
148 max_cmd_transfer: read_u32(control, sbrm_reg::MAX_CMD_TRANSFER)?,
149 max_ack_transfer: read_u32(control, sbrm_reg::MAX_ACK_TRANSFER)?,
150 num_stream_channels: read_u32(control, sbrm_reg::NUM_STREAM_CHANNELS)?,
151 sirm_address: read_u64(control, sbrm_reg::SIRM_ADDRESS)?,
152 sirm_length: read_u32(control, sbrm_reg::SIRM_LENGTH)?,
153 eirm_address: read_u64(control, sbrm_reg::EIRM_ADDRESS)?,
154 eirm_length: read_u32(control, sbrm_reg::EIRM_LENGTH)?,
155 })
156 }
157}
158
159mod sirm_reg {
165 pub const SIRM_INFO: u64 = 0x0000;
166 pub const SIRM_CONTROL: u64 = 0x0004;
167 pub const REQ_PAYLOAD_SIZE: u64 = 0x0008;
168 pub const REQ_LEADER_SIZE: u64 = 0x0010;
169 pub const REQ_TRAILER_SIZE: u64 = 0x0014;
170 pub const MAX_LEADER_SIZE: u64 = 0x0018;
171 pub const MAX_TRAILER_SIZE: u64 = 0x001C;
172 pub const PAYLOAD_SIZE: u64 = 0x0020;
173 pub const PAYLOAD_COUNT: u64 = 0x0028;
174 pub const TRANSFER1_SIZE: u64 = 0x002C;
175 pub const TRANSFER2_SIZE: u64 = 0x0030;
176 pub const MAX_PAYLOAD_TRANSFER: u64 = 0x0034;
177}
178
179#[derive(Debug, Clone)]
181pub struct Sirm {
182 pub base: u64,
183 pub info: u32,
184 pub control: u32,
185 pub req_payload_size: u64,
186 pub req_leader_size: u32,
187 pub req_trailer_size: u32,
188 pub max_leader_size: u32,
189 pub max_trailer_size: u32,
190 pub payload_size: u64,
191 pub payload_count: u32,
192 pub transfer1_size: u32,
193 pub transfer2_size: u32,
194 pub max_payload_transfer: u32,
195}
196
197impl Sirm {
198 pub fn read_from<T: UsbTransfer>(
200 control: &mut ControlChannel<T>,
201 base: u64,
202 ) -> Result<Self, U3vError> {
203 let read_u32 = |ctrl: &mut ControlChannel<T>, off: u64| -> Result<u32, U3vError> {
204 let bytes = ctrl.read_mem(base + off, 4)?;
205 Ok(read_u32_be(&bytes))
206 };
207 let read_u64 = |ctrl: &mut ControlChannel<T>, off: u64| -> Result<u64, U3vError> {
208 let bytes = ctrl.read_mem(base + off, 8)?;
209 Ok(read_u64_be(&bytes))
210 };
211
212 Ok(Self {
213 base,
214 info: read_u32(control, sirm_reg::SIRM_INFO)?,
215 control: read_u32(control, sirm_reg::SIRM_CONTROL)?,
216 req_payload_size: read_u64(control, sirm_reg::REQ_PAYLOAD_SIZE)?,
217 req_leader_size: read_u32(control, sirm_reg::REQ_LEADER_SIZE)?,
218 req_trailer_size: read_u32(control, sirm_reg::REQ_TRAILER_SIZE)?,
219 max_leader_size: read_u32(control, sirm_reg::MAX_LEADER_SIZE)?,
220 max_trailer_size: read_u32(control, sirm_reg::MAX_TRAILER_SIZE)?,
221 payload_size: read_u64(control, sirm_reg::PAYLOAD_SIZE)?,
222 payload_count: read_u32(control, sirm_reg::PAYLOAD_COUNT)?,
223 transfer1_size: read_u32(control, sirm_reg::TRANSFER1_SIZE)?,
224 transfer2_size: read_u32(control, sirm_reg::TRANSFER2_SIZE)?,
225 max_payload_transfer: read_u32(control, sirm_reg::MAX_PAYLOAD_TRANSFER)?,
226 })
227 }
228}
229
230impl Sirm {
231 pub fn enable<T: UsbTransfer>(&self, control: &mut ControlChannel<T>) -> Result<(), U3vError> {
233 let val = self.control | 0x0000_0001;
234 control.write_mem(self.base + sirm_reg::SIRM_CONTROL, &val.to_be_bytes())
235 }
236
237 pub fn disable<T: UsbTransfer>(&self, control: &mut ControlChannel<T>) -> Result<(), U3vError> {
239 let val = self.control & !0x0000_0001;
240 control.write_mem(self.base + sirm_reg::SIRM_CONTROL, &val.to_be_bytes())
241 }
242
243 pub fn configure<T: UsbTransfer>(
245 &self,
246 control: &mut ControlChannel<T>,
247 payload_size: u64,
248 leader_size: u32,
249 trailer_size: u32,
250 ) -> Result<(), U3vError> {
251 control.write_mem(
252 self.base + sirm_reg::REQ_PAYLOAD_SIZE,
253 &payload_size.to_be_bytes(),
254 )?;
255 control.write_mem(
256 self.base + sirm_reg::REQ_LEADER_SIZE,
257 &leader_size.to_be_bytes(),
258 )?;
259 control.write_mem(
260 self.base + sirm_reg::REQ_TRAILER_SIZE,
261 &trailer_size.to_be_bytes(),
262 )?;
263 Ok(())
264 }
265}
266
267#[derive(Debug, Clone)]
273pub struct ManifestEntry {
274 pub file_address: u64,
275 pub file_size: u64,
276}
277
278impl ManifestEntry {
279 pub fn read_first<T: UsbTransfer>(
283 control: &mut ControlChannel<T>,
284 table_address: u64,
285 ) -> Result<Self, U3vError> {
286 let header = control.read_mem(table_address, 4)?;
289 let count = read_u32_be(&header);
290 if count == 0 {
291 return Err(U3vError::Protocol("manifest table is empty".into()));
292 }
293
294 let entry_offset = table_address + 8;
296 let entry_data = control.read_mem(entry_offset, 24)?;
297 let file_address = read_u64_be(&entry_data[8..16]);
299 let file_size = read_u64_be(&entry_data[16..24]);
300
301 Ok(Self {
302 file_address,
303 file_size,
304 })
305 }
306}
307
308fn read_u32_be(data: &[u8]) -> u32 {
313 let mut buf = &data[..4];
314 buf.get_u32()
315}
316
317fn read_u64_be(data: &[u8]) -> u64 {
318 let mut buf = &data[..8];
319 buf.get_u64()
320}
321
322fn parse_nul_string(data: &[u8]) -> String {
323 let end = data.iter().position(|&b| b == 0).unwrap_or(data.len());
324 String::from_utf8_lossy(&data[..end]).into_owned()
325}
326
327#[cfg(test)]
332mod tests {
333 use super::*;
334 use crate::usb::MockUsbTransfer;
335 use bytes::{BufMut, BytesMut};
336 use std::sync::Arc;
337
338 const EP_OUT: u8 = 0x01;
339 const EP_IN: u8 = 0x81;
340 const ACK_PREFIX_LE: u32 = 0x4356_3341;
341 const PREFIX_SIZE: usize = 12;
342
343 fn success_ack(request_id: u16, payload: &[u8]) -> Vec<u8> {
345 let mut buf = BytesMut::with_capacity(PREFIX_SIZE + payload.len());
346 buf.put_u32_le(ACK_PREFIX_LE);
347 buf.put_u16_le(0x0000); buf.put_u16_le(0x0085); buf.put_u16_le(payload.len() as u16);
350 buf.put_u16_le(request_id);
351 buf.extend_from_slice(payload);
352 buf.to_vec()
353 }
354
355 fn enqueue_read_responses(
358 mock: &MockUsbTransfer,
359 ep_in: u8,
360 start_req_id: u16,
361 payloads: &[Vec<u8>],
362 ) -> u16 {
363 let mut req_id = start_req_id;
364 for payload in payloads {
365 mock.enqueue_read(ep_in, success_ack(req_id, payload));
366 req_id = req_id.wrapping_add(1);
367 }
368 req_id
369 }
370
371 #[test]
372 fn parse_nul_terminated_string() {
373 let mut data = vec![0u8; 64];
374 let s = b"TestCamera";
375 data[..s.len()].copy_from_slice(s);
376 assert_eq!(parse_nul_string(&data), "TestCamera");
377 }
378
379 #[test]
380 fn parse_string_no_nul() {
381 let data = b"FullBuffer64Chars";
382 assert_eq!(parse_nul_string(data), "FullBuffer64Chars");
383 }
384
385 #[test]
386 fn sbrm_read_from_mock() {
387 let mock = Arc::new(MockUsbTransfer::new());
388 let mut ch = ControlChannel::new(Arc::clone(&mock), EP_IN, EP_OUT, 1024, 1024);
389
390 let sbrm_base: u64 = 0x1_0000;
391 let mut req_id: u16 = 0;
392
393 let payloads: Vec<Vec<u8>> = vec![
396 0x0001_0000u32.to_be_bytes().to_vec(), 1024u32.to_be_bytes().to_vec(), 1024u32.to_be_bytes().to_vec(), 1u32.to_be_bytes().to_vec(), 0x0002_0000u64.to_be_bytes().to_vec(), 256u32.to_be_bytes().to_vec(), 0x0003_0000u64.to_be_bytes().to_vec(), 64u32.to_be_bytes().to_vec(), ];
405 req_id = enqueue_read_responses(&mock, EP_IN, req_id, &payloads);
406 let _ = req_id;
407
408 let sbrm = Sbrm::read_from(&mut ch, sbrm_base).unwrap();
409 assert_eq!(sbrm.u3v_version, 0x0001_0000);
410 assert_eq!(sbrm.max_cmd_transfer, 1024);
411 assert_eq!(sbrm.max_ack_transfer, 1024);
412 assert_eq!(sbrm.num_stream_channels, 1);
413 assert_eq!(sbrm.sirm_address, 0x0002_0000);
414 assert_eq!(sbrm.sirm_length, 256);
415 assert_eq!(sbrm.eirm_address, 0x0003_0000);
416 assert_eq!(sbrm.eirm_length, 64);
417 }
418
419 #[test]
420 fn manifest_entry_read_first() {
421 let mock = Arc::new(MockUsbTransfer::new());
422 let mut ch = ControlChannel::new(Arc::clone(&mock), EP_IN, EP_OUT, 1024, 1024);
423
424 let table_addr: u64 = 0x5000;
425 mock.enqueue_read(EP_IN, success_ack(0, &1u32.to_be_bytes()));
427 let mut entry = BytesMut::with_capacity(24);
429 entry.put_u64(0); entry.put_u64(0x0010_0000); entry.put_u64(4096); mock.enqueue_read(EP_IN, success_ack(1, &entry));
433
434 let manifest = ManifestEntry::read_first(&mut ch, table_addr).unwrap();
435 assert_eq!(manifest.file_address, 0x0010_0000);
436 assert_eq!(manifest.file_size, 4096);
437 }
438}