summary refs log tree commit diff
path: root/usb_util/src/config_descriptor.rs
blob: 8aebbac596d7fdde28622b72859e17ef3ca336eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ops::Deref;

use crate::bindings::{self, libusb_config_descriptor};
use crate::interface_descriptor::InterfaceDescriptor;

/// ConfigDescriptor wraps libusb_config_descriptor.
pub struct ConfigDescriptor {
    descriptor: *mut libusb_config_descriptor,
}

impl Drop for ConfigDescriptor {
    // Free configuration descriptor.
    // Safe because 'self' is intialized with a valid libusb_config_descriptor from libusb
    // functions.
    fn drop(&mut self) {
        unsafe {
            bindings::libusb_free_config_descriptor(self.descriptor);
        }
    }
}

impl ConfigDescriptor {
    /// Build ConfigDescriptor. 'descriptor' should be a valid pointer from
    /// libusb_config_descriptor. This function will panic if it's null.
    pub unsafe fn new(descriptor: *mut libusb_config_descriptor) -> ConfigDescriptor {
        assert!(!descriptor.is_null());
        ConfigDescriptor { descriptor }
    }

    /// Get interface by number and alt setting.
    pub fn get_interface_descriptor(
        &self,
        interface_num: u8,
        alt_setting: i32,
    ) -> Option<InterfaceDescriptor> {
        let config_descriptor = self.deref();
        if interface_num >= config_descriptor.bNumInterfaces {
            return None;
        }
        // Safe because interface num is checked.
        let interface = unsafe { &*(config_descriptor.interface.offset(interface_num as isize)) };

        if alt_setting >= interface.num_altsetting {
            return None;
        }
        // Safe because setting num is checked.
        unsafe {
            Some(InterfaceDescriptor::new(
                &*(interface.altsetting.offset(alt_setting as isize)),
            ))
        }
    }
}

impl Deref for ConfigDescriptor {
    type Target = libusb_config_descriptor;

    fn deref(&self) -> &libusb_config_descriptor {
        // Safe because 'self.descriptor' is valid.
        unsafe { &*(self.descriptor) }
    }
}