usb_descriptor_decoder/descriptors/desc_uvc/
uvc_interfaces.rs

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                    //this descriptor may change with different uvc version
374                    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}