summary refs log tree commit diff
path: root/usb_util/src/device_handle.rs
blob: e07f6f2675b14c6ffcb90e8901301d0200e67d0f (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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 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::os::raw::c_int;
use std::sync::Arc;

use bindings;
use error::{Error, Result};
use libusb_context::LibUsbContextInner;

/// DeviceHandle wraps libusb_device_handle.
pub struct DeviceHandle {
    _context: Arc<LibUsbContextInner>,
    handle: *mut bindings::libusb_device_handle,
}

unsafe impl Send for DeviceHandle {}

impl Drop for DeviceHandle {
    fn drop(&mut self) {
        // Safe because self.handle is a valid pointer to libusb_device_handle.
        unsafe {
            bindings::libusb_close(self.handle);
        }
    }
}

impl DeviceHandle {
    /// Create a new DeviceHande. 'handle' should be a valid pointer to libusb_device_handle.
    pub unsafe fn new(
        ctx: Arc<LibUsbContextInner>,
        handle: *mut bindings::libusb_device_handle,
    ) -> DeviceHandle {
        DeviceHandle {
            _context: ctx,
            handle,
        }
    }

    /// Get bConfigurationValue of the currently active configuration.
    pub fn get_active_configuration(&self) -> Result<i32> {
        let mut config: c_int = 0;
        // Safe because 'self.handle' is a valid pointer to device handle and '&mut config' is a
        // valid output location.
        try_libusb!(unsafe { bindings::libusb_get_configuration(self.handle, &mut config) });
        Ok(config as i32)
    }

    /// Set active configuration for a device.
    pub fn set_active_configuration(&mut self, config: i32) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe { bindings::libusb_set_configuration(self.handle, config as c_int) });
        Ok(())
    }

    /// Claim an interface on this deivce handle.
    pub fn claim_interface(&self, interface_number: i32) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe { bindings::libusb_claim_interface(self.handle, interface_number) });
        Ok(())
    }

    /// Release an interface previously claimed with libusb_claim_interface.
    pub fn release_interface(&self, interface_number: i32) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe { bindings::libusb_release_interface(self.handle, interface_number) });
        Ok(())
    }

    /// Perform a USB port reset to reinitialize a device.
    pub fn reset_device(&self) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe { bindings::libusb_reset_device(self.handle) });
        Ok(())
    }

    /// Determine if a kernel driver is active on an interface.
    pub fn kernel_driver_active(&self, interface_number: i32) -> Result<bool> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        let v = try_libusb!(unsafe {
            bindings::libusb_kernel_driver_active(self.handle, interface_number)
        });
        Ok(v != 0)
    }

    /// Detach a kernel driver from an interface.
    pub fn detach_kernel_driver(&self, interface_number: i32) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe {
            bindings::libusb_detach_kernel_driver(self.handle, interface_number)
        });
        Ok(())
    }

    /// Re-attach an interfae's kernel driver, which was previously detached using
    /// detach_kernel_driver.
    pub fn attach_kernel_driver(&self, interface_number: i32) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe {
            bindings::libusb_attach_kernel_driver(self.handle, interface_number)
        });
        Ok(())
    }

    /// Active an alternate setting for an interface.
    pub fn set_interface_alt_setting(
        &self,
        interface_number: i32,
        alternative_setting: i32,
    ) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe {
            bindings::libusb_set_interface_alt_setting(
                self.handle,
                interface_number,
                alternative_setting,
            )
        });
        Ok(())
    }

    /// Clear the halt/stall condition for an endpoint.
    pub fn clear_halt(&self, endpoint: u8) -> Result<()> {
        // Safe because 'self.handle' is a valid pointer to device handle.
        try_libusb!(unsafe { bindings::libusb_clear_halt(self.handle, endpoint) });
        Ok(())
    }
}