Struct hidapi::HidDevice

source ·
pub struct HidDevice { /* private fields */ }
Expand description

Object for accessing HID device

Implementations§

source§

impl HidDevice

source

pub fn check_error(&self) -> HidResult<HidError>

Get the last error, which happened in the underlying hidapi C library.

The Ok() variant of the result will contain a HidError::HidApiError.

When Err() is returned, then acquiring the error string from the hidapi C library failed. The contained HidError is the cause, why no error could be fetched.

Examples found in repository?
examples/static_lifetime_bound.rs (line 39)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
fn test_lt() -> Rc<HidDevice> {
    let api = HidApi::new().expect("Hidapi init failed");

    let mut devices = api.device_list();

    let dev_info = devices
        .next()
        .expect("There is not a single hid device available");

    let dev = Rc::new(
        api.open(dev_info.vendor_id(), dev_info.product_id())
            .expect("Can not open device"),
    );

    let dev_1 = dev.clone();
    requires_static_lt_bound(move || {
        println!("{}", dev_1.check_error().unwrap()); //<! Can be captured by closure with static lt
    });

    dev //<! Can be returned from a function, which exceeds the lifetime of the API context
}
source

pub fn write(&self, data: &[u8]) -> HidResult<usize>

The first byte of data must contain the Report ID. For devices which only support a single report, this must be set to 0x0. The remaining bytes contain the report data. Since the Report ID is mandatory, calls to write() will always contain one more byte than the report contains. For example, if a hid report is 16 bytes long, 17 bytes must be passed to write(), the Report ID (or 0x0, for devices with a single report), followed by the report data (16 bytes). In this example, the length passed in would be 17. write() will send the data on the first OUT endpoint, if one exists. If it does not, it will send the data through the Control Endpoint (Endpoint 0).

Examples found in repository?
examples/logitech_gprox.rs (line 24)
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
fn main() -> Result<(), Box<dyn Error>> {
    let vol = std::env::args()
        .nth(1)
        .map(|arg| arg.parse::<u8>())
        .ok_or("missing sidechannel volume arg")??
        .min(100);

    let api = HidApi::new()?;
    let dev = api.open(0x046d, 0x0aaa)?;

    println!("Setting sidechannel volume to {}", vol);

    dev.write(&[0x11, 0xff, 0x05, 0x1c, vol])?;

    Ok(())
}
source

pub fn read(&self, buf: &mut [u8]) -> HidResult<usize>

Input reports are returned to the host through the ‘INTERRUPT IN’ endpoint. The first byte will contain the Report number if the device uses numbered reports.

Examples found in repository?
examples/readhid.rs (line 22)
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
fn main() {
    let api = HidApi::new().expect("Failed to create API instance");

    let joystick = api.open(1103, 45320).expect("Failed to open device");

    loop {
        let mut buf = [0u8; 256];
        let res = joystick.read(&mut buf[..]).unwrap();

        let mut data_string = String::new();

        for u in &buf[..res] {
            data_string.push_str(&(u.to_string() + "\t"));
        }

        println!("{}", data_string);
    }
}
More examples
Hide additional examples
examples/open_first_device.rs (line 37)
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
    fn run() -> Result<(), HidError> {
        let hidapi = HidApi::new()?;

        let device_info = hidapi
            .device_list()
            .next()
            .expect("No devices are available!")
            .clone();

        println!(
            "Opening device:\n VID: {:04x}, PID: {:04x}\n",
            device_info.vendor_id(),
            device_info.product_id()
        );

        let device = device_info.open_device(&hidapi)?;

        let mut buf = vec![0; 64];

        println!("Reading data from device ...\n");

        loop {
            let len = device.read(&mut buf)?;
            println!("{:?}", &buf[..len]);
        }
    }
source

pub fn read_timeout(&self, buf: &mut [u8], timeout: i32) -> HidResult<usize>

Input reports are returned to the host through the ‘INTERRUPT IN’ endpoint. The first byte will contain the Report number if the device uses numbered reports. Timeout measured in milliseconds, set -1 for blocking wait.

Examples found in repository?
examples/co2mon.rs (line 114)
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
130
131
132
133
134
135
136
fn main() {
    let api = HidApi::new().expect("HID API object creation failed");

    let dev = open_device(&api);

    dev.send_feature_report(&[0; PACKET_SIZE])
        .expect("Feature report failed");

    println!(
        "Manufacurer:\t{:?}",
        dev.get_manufacturer_string()
            .expect("Failed to read manufacurer string")
    );
    println!(
        "Product:\t{:?}",
        dev.get_product_string()
            .expect("Failed to read product string")
    );
    println!(
        "Serial number:\t{:?}",
        dev.get_serial_number_string()
            .expect("Failed to read serial number")
    );

    loop {
        let mut buf = [0; PACKET_SIZE];
        match dev.read_timeout(&mut buf[..], HID_TIMEOUT) {
            Ok(PACKET_SIZE) => (),
            Ok(res) => {
                println!("Error: unexpected length of data: {}/{}", res, PACKET_SIZE);
                continue;
            }
            Err(err) => {
                println!("Error: {:}", err);
                sleep(Duration::from_secs(RETRY_SEC));
                continue;
            }
        }
        match decode_buf(buf) {
            CO2Result::Temperature(val) => println!("Temp:\t{:?}", val),
            CO2Result::Concentration(val) => println!("Conc:\t{:?}", val),
            CO2Result::Unknown(..) => (),
            CO2Result::Error(val) => {
                println!("Error:\t{}", val);
                sleep(Duration::from_secs(RETRY_SEC));
            }
        }
    }
}
source

pub fn send_feature_report(&self, data: &[u8]) -> HidResult<()>

Send a Feature report to the device. Feature reports are sent over the Control endpoint as a Set_Report transfer. The first byte of data must contain the ‘Report ID’. For devices which only support a single report, this must be set to 0x0. The remaining bytes contain the report data. Since the ‘Report ID’ is mandatory, calls to send_feature_report() will always contain one more byte than the report contains. For example, if a hid report is 16 bytes long, 17 bytes must be passed to send_feature_report(): ‘the Report ID’ (or 0x0, for devices which do not use numbered reports), followed by the report data (16 bytes). In this example, the length passed in would be 17.

Examples found in repository?
examples/co2mon.rs (line 93)
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
130
131
132
133
134
135
136
fn main() {
    let api = HidApi::new().expect("HID API object creation failed");

    let dev = open_device(&api);

    dev.send_feature_report(&[0; PACKET_SIZE])
        .expect("Feature report failed");

    println!(
        "Manufacurer:\t{:?}",
        dev.get_manufacturer_string()
            .expect("Failed to read manufacurer string")
    );
    println!(
        "Product:\t{:?}",
        dev.get_product_string()
            .expect("Failed to read product string")
    );
    println!(
        "Serial number:\t{:?}",
        dev.get_serial_number_string()
            .expect("Failed to read serial number")
    );

    loop {
        let mut buf = [0; PACKET_SIZE];
        match dev.read_timeout(&mut buf[..], HID_TIMEOUT) {
            Ok(PACKET_SIZE) => (),
            Ok(res) => {
                println!("Error: unexpected length of data: {}/{}", res, PACKET_SIZE);
                continue;
            }
            Err(err) => {
                println!("Error: {:}", err);
                sleep(Duration::from_secs(RETRY_SEC));
                continue;
            }
        }
        match decode_buf(buf) {
            CO2Result::Temperature(val) => println!("Temp:\t{:?}", val),
            CO2Result::Concentration(val) => println!("Conc:\t{:?}", val),
            CO2Result::Unknown(..) => (),
            CO2Result::Error(val) => {
                println!("Error:\t{}", val);
                sleep(Duration::from_secs(RETRY_SEC));
            }
        }
    }
}
source

pub fn get_feature_report(&self, buf: &mut [u8]) -> HidResult<usize>

Set the first byte of buf to the ‘Report ID’ of the report to be read. Upon return, the first byte will still contain the Report ID, and the report data will start in buf[1].

source

pub fn set_blocking_mode(&self, blocking: bool) -> HidResult<()>

Set the device handle to be in blocking or in non-blocking mode. In non-blocking mode calls to read() will return immediately with an empty slice if there is no data to be read. In blocking mode, read() will wait (block) until there is data to read before returning. Modes can be changed at any time.

source

pub fn get_manufacturer_string(&self) -> HidResult<Option<String>>

Get The Manufacturer String from a HID device.

Examples found in repository?
examples/co2mon.rs (line 98)
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
130
131
132
133
134
135
136
fn main() {
    let api = HidApi::new().expect("HID API object creation failed");

    let dev = open_device(&api);

    dev.send_feature_report(&[0; PACKET_SIZE])
        .expect("Feature report failed");

    println!(
        "Manufacurer:\t{:?}",
        dev.get_manufacturer_string()
            .expect("Failed to read manufacurer string")
    );
    println!(
        "Product:\t{:?}",
        dev.get_product_string()
            .expect("Failed to read product string")
    );
    println!(
        "Serial number:\t{:?}",
        dev.get_serial_number_string()
            .expect("Failed to read serial number")
    );

    loop {
        let mut buf = [0; PACKET_SIZE];
        match dev.read_timeout(&mut buf[..], HID_TIMEOUT) {
            Ok(PACKET_SIZE) => (),
            Ok(res) => {
                println!("Error: unexpected length of data: {}/{}", res, PACKET_SIZE);
                continue;
            }
            Err(err) => {
                println!("Error: {:}", err);
                sleep(Duration::from_secs(RETRY_SEC));
                continue;
            }
        }
        match decode_buf(buf) {
            CO2Result::Temperature(val) => println!("Temp:\t{:?}", val),
            CO2Result::Concentration(val) => println!("Conc:\t{:?}", val),
            CO2Result::Unknown(..) => (),
            CO2Result::Error(val) => {
                println!("Error:\t{}", val);
                sleep(Duration::from_secs(RETRY_SEC));
            }
        }
    }
}
source

pub fn get_product_string(&self) -> HidResult<Option<String>>

Get The Manufacturer String from a HID device.

Examples found in repository?
examples/co2mon.rs (line 103)
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
130
131
132
133
134
135
136
fn main() {
    let api = HidApi::new().expect("HID API object creation failed");

    let dev = open_device(&api);

    dev.send_feature_report(&[0; PACKET_SIZE])
        .expect("Feature report failed");

    println!(
        "Manufacurer:\t{:?}",
        dev.get_manufacturer_string()
            .expect("Failed to read manufacurer string")
    );
    println!(
        "Product:\t{:?}",
        dev.get_product_string()
            .expect("Failed to read product string")
    );
    println!(
        "Serial number:\t{:?}",
        dev.get_serial_number_string()
            .expect("Failed to read serial number")
    );

    loop {
        let mut buf = [0; PACKET_SIZE];
        match dev.read_timeout(&mut buf[..], HID_TIMEOUT) {
            Ok(PACKET_SIZE) => (),
            Ok(res) => {
                println!("Error: unexpected length of data: {}/{}", res, PACKET_SIZE);
                continue;
            }
            Err(err) => {
                println!("Error: {:}", err);
                sleep(Duration::from_secs(RETRY_SEC));
                continue;
            }
        }
        match decode_buf(buf) {
            CO2Result::Temperature(val) => println!("Temp:\t{:?}", val),
            CO2Result::Concentration(val) => println!("Conc:\t{:?}", val),
            CO2Result::Unknown(..) => (),
            CO2Result::Error(val) => {
                println!("Error:\t{}", val);
                sleep(Duration::from_secs(RETRY_SEC));
            }
        }
    }
}
source

pub fn get_serial_number_string(&self) -> HidResult<Option<String>>

Get The Serial Number String from a HID device.

Examples found in repository?
examples/co2mon.rs (line 108)
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
130
131
132
133
134
135
136
fn main() {
    let api = HidApi::new().expect("HID API object creation failed");

    let dev = open_device(&api);

    dev.send_feature_report(&[0; PACKET_SIZE])
        .expect("Feature report failed");

    println!(
        "Manufacurer:\t{:?}",
        dev.get_manufacturer_string()
            .expect("Failed to read manufacurer string")
    );
    println!(
        "Product:\t{:?}",
        dev.get_product_string()
            .expect("Failed to read product string")
    );
    println!(
        "Serial number:\t{:?}",
        dev.get_serial_number_string()
            .expect("Failed to read serial number")
    );

    loop {
        let mut buf = [0; PACKET_SIZE];
        match dev.read_timeout(&mut buf[..], HID_TIMEOUT) {
            Ok(PACKET_SIZE) => (),
            Ok(res) => {
                println!("Error: unexpected length of data: {}/{}", res, PACKET_SIZE);
                continue;
            }
            Err(err) => {
                println!("Error: {:}", err);
                sleep(Duration::from_secs(RETRY_SEC));
                continue;
            }
        }
        match decode_buf(buf) {
            CO2Result::Temperature(val) => println!("Temp:\t{:?}", val),
            CO2Result::Concentration(val) => println!("Conc:\t{:?}", val),
            CO2Result::Unknown(..) => (),
            CO2Result::Error(val) => {
                println!("Error:\t{}", val);
                sleep(Duration::from_secs(RETRY_SEC));
            }
        }
    }
}
source

pub fn get_indexed_string(&self, index: i32) -> HidResult<Option<String>>

Get a string from a HID device, based on its string index.

source

pub fn get_device_info(&self) -> HidResult<DeviceInfo>

Get DeviceInfo from a HID device.

Trait Implementations§

source§

impl Debug for HidDevice

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Drop for HidDevice

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl Send for HidDevice

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.