1use core::ptr;
2
3use alloc::vec::Vec;
4
5use log::trace;
6use num_derive::{FromPrimitive, ToPrimitive};
7use num_traits::{FromPrimitive, ToPrimitive};
8
9#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
10#[allow(non_camel_case_types)]
11#[repr(u8)]
12pub enum UVCStandardVideoInterfaceClass {
13 CC_Video = 0x0e,
14}
15
16#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
17#[allow(non_camel_case_types)]
18#[repr(u8)]
19pub enum UVCInterfaceSubclass {
20 UNDEFINED = 0x00,
21 VIDEOCONTROL = 0x01,
22 VIDEOSTREAMING = 0x02,
23 VIDEO_INTERFACE_COLLECTION = 0x03,
24}
25
26#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
27#[allow(non_camel_case_types)]
28#[repr(u8)]
29pub enum UVCControlInterfaceSubclass {
30 DESCRIPTOR_UNDEFINED = 0x00,
31 HEADER = 0x01,
32 INPUT_TERMINAL = 0x02,
33 OUTPUT_TERMINAL = 0x03,
34 SELECTOR_UNIT = 0x04,
35 PROCESSING_UNIT = 0x05,
36 EXTENSION_UNIT = 0x06,
37 ENCODING_UNIT = 0x07,
38}
39
40#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive, ToPrimitive)]
41#[allow(non_camel_case_types)]
42#[repr(u8)]
43pub enum UVCVSInterfaceSubclass {
44 UNDEFINED = 0x00,
45 INPUT_HEADER = 0x01,
46 OUTPUT_HEADER = 0x02,
47 STILL_IMAGE_FRAME = 0x03,
48 FORMAT_UNCOMPRESSED = 0x04,
49 FRAME_UNCOMPRESSED = 0x05,
50 FORMAT_MJPEG = 0x06,
51 FRAME_MJPEG = 0x07,
52 FORMAT_MPEG2TS = 0x0A,
53 FORMAT_DV = 0x0C,
54 COLORFORMAT = 0x0D,
55 FORMAT_FRAME_BASED = 0x10,
56 FRAME_FRAME_BASED = 0x11,
57 FORMAT_STREAM_BASED = 0x12,
58 FORMAT_H264 = 0x13,
59 FRAME_H264 = 0x14,
60 FORMAT_H264_SIMULCAST = 0x15,
61 FORMAT_VP8 = 0x16,
62 FRAME_VP8 = 0x17,
63 FORMAT_VP8_SIMULCAST = 0x18,
64}
65
66#[derive(FromPrimitive, Copy, Clone, Debug, PartialEq)]
67#[allow(non_camel_case_types)]
68#[repr(u8)]
69pub enum UVCStandardVideoInterfaceProtocols {
70 PC_PROTOCOL_UNDEFINED = 0x00,
71 PC_PROTOCOL_15 = 0x01,
72}
73
74#[derive(Debug, Clone)]
75pub enum UVCInterface {
76 Control(UVCControlInterface),
77 Streaming(UVCStreamingInterface),
78}
79
80#[derive(Debug, Clone)]
81pub enum UVCControlInterface {
82 Header(UVCControlInterfaceHeader),
83 OutputTerminal(UVCControlInterfaceOutputTerminal),
84 InputTerminal(UVCControlInterfaceInputTerminal),
85 ExtensionUnit(UVCControlInterfaceExtensionUnit),
86 ProcessingUnit(UVCControlInterfaceProcessingUnit),
87}
88
89#[derive(Debug, Clone)]
90pub enum UVCStreamingInterface {
91 InputHeader(UVCVSInterfaceInputHeader),
92 OutputHeader,
93 StillImageFrame(UVCVSInterfaceStillImageFrame),
94 FormatUncompressed(UVCVSInterfaceFormatUncompressed),
95 FrameUncompressed(UVCVSInterfaceFrameUncompressed),
96 FormatMjpeg(UVCVSInterfaceFormatMJPEG),
97 FrameMjpeg(UVCVSInterfaceFrameMJPEG),
98 FormatMpeg2ts,
99 FormatDv,
100 COLORFORMAT(UVCVSInterfaceColorFormat),
101 FormatFrameBased,
102 FrameFrameBased,
103 FormatStreamBased,
104 FormatH264,
105 FrameH264,
106 FormatH264Simulcast,
107 FormatVp8,
108 FrameVp8,
109 FormatVp8Simulcast,
110}
111
112#[derive(Clone, Debug)]
113#[allow(non_camel_case_types)]
114pub struct UVCControlInterfaceHeader {
115 length: u8,
116 descriptor_type: u8,
117 descriptor_sub_type: u8,
118 bcd_uvc: u16,
119 total_length: u16,
120 clock_frequency: u32,
121 in_collection: u8,
122 interface_nr: Vec<u8>,
123}
124
125#[derive(Clone, Debug)]
126#[allow(non_camel_case_types)]
127pub struct UVCControlInterfaceInputTerminal {
128 length: u8,
129 descriptor_type: u8,
130 descriptor_sub_type: u8,
131 terminal_id: u8,
132 terminal_type: u16,
133 associated_terminal: u8,
134 string_index_terminal: u8,
135 reserved: Vec<u8>,
136}
137
138#[derive(Clone, Debug)]
139#[allow(non_camel_case_types)]
140pub struct UVCControlInterfaceOutputTerminal {
141 length: u8,
142 descriptor_type: u8,
143 descriptor_sub_type: u8,
144 terminal_id: u8,
145 terminal_type: u16,
146 associated_terminal: u8,
147 source_id: u8,
148 string_index_terminal: u8,
149 reserved: Vec<u8>,
150}
151
152#[derive(Clone, Debug)]
153#[allow(non_camel_case_types)]
154pub struct UVCControlInterfaceExtensionUnit {
155 length: u8,
156 descriptor_type: u8,
157 descriptor_sub_type: u8,
158 unit_id: u8,
159 guid_extension_code: [u8; 16],
160 num_controls: u8,
161 nr_in_pins: u8,
162 source_ids: Vec<u8>,
163 control_size: u8,
164 controls: Vec<u8>,
165 extension: u8,
166}
167
168#[derive(Clone, Debug)]
169#[allow(non_camel_case_types)]
170pub struct UVCControlInterfaceProcessingUnit {
171 length: u8,
172 descriptor_type: u8,
173 descriptor_sub_type: u8,
174 unit_id: u8,
175 source_id: u8,
176 max_multiplier: u16,
177 control_size: u8,
178 controls: [u8; 3],
179 processing: u8,
180 video_standards: u8,
181}
182
183#[derive(FromPrimitive, Copy, Clone, Debug, PartialEq)]
184#[allow(non_camel_case_types)]
185#[repr(u16)]
186pub enum UVCCONTROLOutputTerminalType {
187 OTT_VendorSpec = 0x300,
188 OTT_Display = 0x301,
189 OTT_MEDIA_TRANSPORT_OUTPUT = 0x302,
190 TT_VendorSpec = 0x0100,
191 TT_Streaming = 0x0101,
192}
193
194#[derive(Clone, Debug)]
195#[allow(non_camel_case_types)]
196pub struct UVCVSInterfaceInputHeader {
197 length: u8,
198 descriptor_type: u8,
199 descriptor_sub_type: u8,
200 num_formats: u8,
201 total_length: u16,
202 endpoint_address: u8,
203 info: u8,
204 terminal_link: u8,
205 still_capture_method: u8,
206 trigger_support: u8,
207 trigger_useage: u8,
208 control_size: u8,
209 interface_nr: Vec<u8>,
210}
211
212#[derive(Clone, Debug)]
213#[allow(non_camel_case_types)]
214pub struct UVCVSInterfaceFormatMJPEG {
215 length: u8,
216 descriptor_type: u8,
217 descriptor_sub_type: u8,
218 format_index: u8,
219 num_frame_descriptors: u8,
220 flags: u8,
221 default_frame_index: u8,
222 aspect_ratio_x: u8,
223 aspect_ratio_y: u8,
224 interlace_flags: u8,
225 is_copy_protect: u8,
226}
227
228#[derive(Clone, Debug)]
229#[allow(non_camel_case_types)]
230pub struct UVCVSInterfaceFrameMJPEG {
231 length: u8,
232 descriptor_type: u8,
233 descriptor_sub_type: u8,
234 frame_index: u8,
235 capabilities: u8,
236 width: u16,
237 height: u16,
238 min_bit_rate: u32,
239 max_bit_rate: u32,
240 max_video_frame_buffer_size: u32,
241 default_frame_interval: u32,
242 frame_interval_type: u8,
243 frame_interval: FrameInterval,
244}
245
246#[derive(Clone, Debug)]
247#[allow(non_camel_case_types)]
248pub struct UVCVSInterfaceStillImageFrame {
249 length: u8,
250 descriptor_type: u8,
251 descriptor_sub_type: u8,
252 endpoint_address: u8,
253 num_image_size_paterns: u8,
254 width_heights: Vec<(u16, u16)>,
255 num_compression_pattern: u8,
256 compressions: Vec<u8>,
257}
258
259#[derive(Clone, Debug)]
260#[allow(non_camel_case_types)]
261pub struct UVCVSInterfaceFormatUncompressed {
262 length: u8,
263 descriptor_type: u8,
264 descriptor_sub_type: u8,
265 format_index: u8,
266 number_frame_descriptor: u8,
267 guid_format: [u8; 16],
268 bits_per_pixel: u8,
269 default_frame_index: u8,
270 aspect_ratio_x: u8,
271 aspect_ratio_y: u8,
272 m_interlace_flags: u8,
273 is_copy_protect: u8,
274}
275
276#[derive(Clone, Debug)]
277#[allow(non_camel_case_types)]
278pub struct UVCVSInterfaceFrameUncompressed {
279 length: u8,
280 descriptor_type: u8,
281 descriptor_sub_type: u8,
282 frame_index: u8,
283 capabilities: u8,
284 width: u16,
285 height: u16,
286 min_bit_rate: u32,
287 max_bit_rate: u32,
288 max_video_frame_buffer_size: u32,
289 default_frame_interval: u32,
290 frame_interval_type: u8,
291 frame_interval: FrameInterval,
292}
293
294#[derive(Clone, Debug)]
295#[allow(non_camel_case_types)]
296pub enum FrameInterval {
297 Continuous((u32, u32, u32)),
298 Discrete(Vec<u32>),
299}
300
301#[derive(Clone, Debug)]
302#[allow(non_camel_case_types)]
303pub struct UVCVSInterfaceColorFormat {
304 length: u8,
305 descriptor_type: u8,
306 descriptor_sub_type: u8,
307 color_primaries: u8,
308 transfer_characteristics: u8,
309 matrix_coefficients: u8,
310}
311
312impl UVCControlInterface {
313 pub fn from_u8_array(raw: &[u8]) -> Self {
314 trace!("buffer:{:?}", raw);
315 let len = raw[0];
316 let descriptor_type = raw[1];
317 let descriptor_sub_type = raw[2];
318 trace!(
319 "subtype{:?}",
320 UVCControlInterfaceSubclass::from_u8(descriptor_sub_type)
321 );
322
323 match UVCControlInterfaceSubclass::from_u8(descriptor_sub_type).unwrap() {
324 UVCControlInterfaceSubclass::DESCRIPTOR_UNDEFINED => panic!("impossible"),
325 UVCControlInterfaceSubclass::HEADER => Self::Header({
326 trace!("header!");
327 let _len_array_nr = len - 12;
328 UVCControlInterfaceHeader {
329 length: len,
330 descriptor_type,
331 descriptor_sub_type,
332 bcd_uvc: u16::from_ne_bytes(raw[3..=4].try_into().unwrap()),
333 total_length: u16::from_ne_bytes(raw[5..=6].try_into().unwrap()),
334 clock_frequency: u32::from_ne_bytes(raw[7..=10].try_into().unwrap()),
335 in_collection: raw[11],
336 interface_nr: {
337 let mut vec = Vec::new();
338 for i in 12..len {
339 vec.push(raw[i as usize]);
340 }
341 vec
342 },
343 }
344 }),
345 UVCControlInterfaceSubclass::INPUT_TERMINAL => {
346 Self::InputTerminal(UVCControlInterfaceInputTerminal {
347 length: len,
348 descriptor_type,
349 descriptor_sub_type,
350 terminal_id: raw[3],
351 terminal_type: u16::from_ne_bytes(raw[4..=5].try_into().unwrap()),
352 associated_terminal: raw[6],
353 string_index_terminal: raw[7],
354 reserved: raw[8..(len as usize)].to_vec(),
355 })
356 }
357 UVCControlInterfaceSubclass::OUTPUT_TERMINAL => {
358 Self::OutputTerminal(UVCControlInterfaceOutputTerminal {
359 length: len,
360 descriptor_type,
361 descriptor_sub_type,
362 terminal_id: raw[3],
363 terminal_type: u16::from_ne_bytes(raw[4..=5].try_into().unwrap()),
364 associated_terminal: raw[6],
365 source_id: raw[7],
366 string_index_terminal: raw[8],
367 reserved: raw[9..(len as usize)].to_vec(),
368 })
369 }
370 UVCControlInterfaceSubclass::SELECTOR_UNIT => todo!(),
371 UVCControlInterfaceSubclass::PROCESSING_UNIT => {
372 Self::ProcessingUnit({
373 unsafe { ptr::read((raw as *const [u8]).cast()) }
375 })
376 }
377 UVCControlInterfaceSubclass::EXTENSION_UNIT => Self::ExtensionUnit({
378 let nr_in_pins = raw[21];
379 let last_in_pin = 21 + nr_in_pins as usize;
380 let in_pins = raw[21..last_in_pin].to_vec();
381
382 let control_size = raw[last_in_pin];
383 let last_control = last_in_pin + control_size as usize;
384 let controls = raw[last_in_pin..last_control].to_vec();
385
386 UVCControlInterfaceExtensionUnit {
387 length: len,
388 descriptor_type,
389 descriptor_sub_type,
390 unit_id: raw[3],
391 guid_extension_code: {
392 let mut codes = [0u8; 16];
393 codes.copy_from_slice(&raw[4..20]);
394 codes
395 },
396 num_controls: raw[20],
397 nr_in_pins,
398 source_ids: in_pins,
399 control_size,
400 controls,
401 extension: raw[last_control],
402 }
403 }),
404 UVCControlInterfaceSubclass::ENCODING_UNIT => todo!(),
405 }
406 }
407}
408
409impl UVCStreamingInterface {
410 pub fn from_u8_array(raw: &[u8]) -> Self {
411 trace!("buffer:{:?}", raw);
412 let len = raw[0];
413 let descriptor_type = raw[1];
414 let descriptor_sub_type = UVCVSInterfaceSubclass::from_u8(raw[2]).unwrap();
415 trace!("subtype{:?}", descriptor_sub_type);
416 match descriptor_sub_type {
417 UVCVSInterfaceSubclass::INPUT_HEADER => Self::InputHeader({
418 let control_size = raw[12];
419 UVCVSInterfaceInputHeader {
420 length: len,
421 descriptor_type,
422 descriptor_sub_type: descriptor_sub_type.to_u8().unwrap(),
423 num_formats: raw[3],
424 total_length: u16::from_ne_bytes(raw[4..=5].try_into().unwrap()),
425 endpoint_address: raw[6],
426 info: raw[7],
427 terminal_link: raw[8],
428 still_capture_method: raw[9],
429 trigger_support: raw[10],
430 trigger_useage: raw[11],
431 control_size,
432 interface_nr: raw[13..(len as usize)].to_vec(),
433 }
434 }),
435 UVCVSInterfaceSubclass::FORMAT_MJPEG => {
436 Self::FormatMjpeg(unsafe { ptr::read((raw as *const [u8]).cast()) })
437 }
438 UVCVSInterfaceSubclass::FRAME_MJPEG => {
439 let frame_interval_type = raw[25];
440
441 let frame_interval = match frame_interval_type {
442 0 => FrameInterval::Continuous((
443 u32::from_ne_bytes(raw[26..30].try_into().unwrap()),
444 u32::from_ne_bytes(raw[30..34].try_into().unwrap()),
445 u32::from_ne_bytes(raw[34..(len as usize)].try_into().unwrap()),
446 )),
447 other => FrameInterval::Discrete(
448 raw[26..((26 + other * 4) as usize)]
449 .chunks(4)
450 .map(|c| u32::from_ne_bytes(c.try_into().unwrap()))
451 .collect(),
452 ),
453 };
454
455 Self::FrameMjpeg(UVCVSInterfaceFrameMJPEG {
456 length: len,
457 descriptor_type,
458 descriptor_sub_type: descriptor_sub_type.to_u8().unwrap(),
459 frame_index: raw[3],
460 capabilities: raw[4],
461 width: u16::from_ne_bytes(raw[5..=6].try_into().unwrap()),
462 height: u16::from_ne_bytes(raw[7..=8].try_into().unwrap()),
463 min_bit_rate: u32::from_ne_bytes(raw[9..13].try_into().unwrap()),
464 max_bit_rate: u32::from_ne_bytes(raw[13..17].try_into().unwrap()),
465 max_video_frame_buffer_size: u32::from_ne_bytes(
466 raw[17..21].try_into().unwrap(),
467 ),
468 default_frame_interval: u32::from_ne_bytes(raw[21..25].try_into().unwrap()),
469 frame_interval_type,
470 frame_interval,
471 })
472 }
473 UVCVSInterfaceSubclass::STILL_IMAGE_FRAME => {
474 let num_image_size_paterns = raw[4];
475 let loc_num_compression_pattern = 5 + 4 * num_image_size_paterns as usize;
476 let width_heights = raw[5..loc_num_compression_pattern]
477 .chunks(4)
478 .map(|t| {
479 (
480 u16::from_ne_bytes(t[0..=1].try_into().unwrap()),
481 u16::from_ne_bytes(t[2..=3].try_into().unwrap()),
482 )
483 })
484 .collect();
485
486 Self::StillImageFrame(UVCVSInterfaceStillImageFrame {
487 length: len,
488 descriptor_type,
489 descriptor_sub_type: descriptor_sub_type.to_u8().unwrap(),
490 endpoint_address: raw[3],
491 num_image_size_paterns,
492 width_heights,
493 num_compression_pattern: raw[loc_num_compression_pattern],
494 compressions: raw[loc_num_compression_pattern + 1..len as usize].to_vec(),
495 })
496 }
497 UVCVSInterfaceSubclass::FORMAT_UNCOMPRESSED => {
498 Self::FormatUncompressed(unsafe { ptr::read((raw as *const [u8]).cast()) })
499 }
500 UVCVSInterfaceSubclass::FRAME_UNCOMPRESSED => {
501 let frame_interval_type = raw[25];
502
503 let frame_interval = match frame_interval_type {
504 0 => FrameInterval::Continuous((
505 u32::from_ne_bytes(raw[26..30].try_into().unwrap()),
506 u32::from_ne_bytes(raw[30..34].try_into().unwrap()),
507 u32::from_ne_bytes(raw[34..(len as usize)].try_into().unwrap()),
508 )),
509 other => FrameInterval::Discrete(
510 raw[26..((26 + other * 4) as usize)]
511 .chunks(4)
512 .map(|c| u32::from_ne_bytes(c.try_into().unwrap()))
513 .collect(),
514 ),
515 };
516
517 Self::FrameUncompressed(UVCVSInterfaceFrameUncompressed {
518 length: len,
519 descriptor_type,
520 descriptor_sub_type: descriptor_sub_type.to_u8().unwrap(),
521 frame_index: raw[3],
522 capabilities: raw[4],
523 width: u16::from_ne_bytes(raw[5..=6].try_into().unwrap()),
524 height: u16::from_ne_bytes(raw[7..=8].try_into().unwrap()),
525 min_bit_rate: u32::from_ne_bytes(raw[9..13].try_into().unwrap()),
526 max_bit_rate: u32::from_ne_bytes(raw[13..17].try_into().unwrap()),
527 max_video_frame_buffer_size: u32::from_ne_bytes(
528 raw[17..21].try_into().unwrap(),
529 ),
530 default_frame_interval: u32::from_ne_bytes(raw[21..25].try_into().unwrap()),
531 frame_interval_type,
532 frame_interval,
533 })
534 }
535 UVCVSInterfaceSubclass::COLORFORMAT => {
536 Self::COLORFORMAT(unsafe { ptr::read((raw as *const [u8]).cast()) })
537 }
538
539 todo => todo!("impl:{:?}", todo),
540 }
541 }
542}