Skip to content
This repository was archived by the owner on Feb 26, 2020. It is now read-only.

Commit 6ce21d3

Browse files
authored
Merge pull request #3 from newpavlov/master
Added missing API methods and documentation. Removed internall HidDevice buffer.
2 parents 212cb15 + 30b9688 commit 6ce21d3

File tree

6 files changed

+425
-98
lines changed

6 files changed

+425
-98
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "hidapi"
3-
version = "0.2.0"
4-
authors = ["Roland Ruckerbauer <[email protected]>", "Osspial <[email protected]"]
3+
version = "0.3.0"
4+
authors = ["Roland Ruckerbauer <[email protected]>", "Osspial <[email protected]", "Artyom Pavlov <[email protected]>"]
55
repository = "https://github.com/Osspial/hidapi-rs"
66
description = "Rust-y wrapper around hidapi"
77
license = "LGPL-3.0+"
@@ -10,7 +10,7 @@ build = "build.rs"
1010
links = "hidapi"
1111

1212
[dependencies]
13-
libc = "0.1.8"
13+
libc = "0.2.15"
1414

1515
[build-dependencies]
1616
gcc = "0.3"

README.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,42 @@
22

33
This crate provides a rust abstraction over the features of the C library
44
[hidapi](https://github.com/signal11/hidapi) by signal11. Based off of
5-
[hidapi_rust](https://github.com/ruabmbua/hidapi_rust) by ruabmbua.
5+
[hidapi_rust](https://github.com/ruabmbua/hidapi_rust) by ruabmbua.
6+
7+
# Usage
8+
9+
This crate is [on crates.io](https://crates.io/crates/hidapi) and can be
10+
used by adding `hidapi` to the dependencies in your project's `Cargo.toml`.
11+
12+
```toml
13+
[dependencies]
14+
hidapi = "0.3"
15+
```
16+
Example:
17+
18+
```rust
19+
extern crate hidapi;
20+
21+
let api = hidapi::HidApi::new().unwrap();
22+
// Print out information about all connected devices
23+
for device in &api.devices() {
24+
println!("{:#?}", device);
25+
}
26+
27+
// Connect to device using its VID and PID
28+
let (VID, PID) = (0x0123, 0x3456);
29+
let device = api.open(VID, PID).unwrap();
30+
31+
// Read data from device
32+
let mut buf = [0u8; 8];
33+
let res = device.read(&mut buf[..]).unwrap();
34+
println!("Read: {:?}", &buf[..res]);
35+
36+
// Write data to device
37+
let buf = [0u8, 1, 2, 3, 4];
38+
let res = device.write(&buf).unwrap();
39+
println!("Wrote: {:?} byte(s)", res);
40+
```
41+
42+
# Documentation
43+
You can generate documentation by running `cargo doc` for this crate.

examples/co2mon.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/****************************************************************************
2+
Copyright (c) 2015 Artyom Pavlov All Rights Reserved.
3+
4+
This file is part of hidapi-rs, based on hidapi_rust by Roland Ruckerbauer.
5+
It's also based on the Oleg Bulatov's work (https://github.com/dmage/co2mon)
6+
7+
hidapi-rs is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation, either version 3 of the License, or
10+
(at your option) any later version.
11+
12+
hidapi-rs is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with hidapi-rs. If not, see <http://www.gnu.org/licenses/>.
19+
****************************************************************************/
20+
21+
22+
//! Opens a KIT MT 8057 CO2 detector and reads data from it. This
23+
//! example will not work unless such an HID is plugged in to your system.
24+
25+
extern crate hidapi;
26+
27+
use hidapi::{HidApi, HidDevice};
28+
use std::thread::sleep;
29+
use std::time::Duration;
30+
31+
const CODE_TEMPERATURE: u8 = 0x42;
32+
const CODE_CONCENTRATION: u8 = 0x50;
33+
const HID_TIMEOUT: i32 = 5000;
34+
const RETRY_SEC: u64 = 1;
35+
const DEV_VID: u16 = 0x04d9;
36+
const DEV_PID: u16 = 0xa052;
37+
const PACKET_SIZE: usize = 8;
38+
39+
enum CO2Result {
40+
Temperature(f32),
41+
Concentration(u16),
42+
Unknown(u8, u16),
43+
Error(&'static str),
44+
}
45+
46+
fn decode_temperature(value: u16) -> f32 {
47+
(value as f32)*0.0625 - 273.15
48+
}
49+
50+
fn decode_buf(buf: [u8; PACKET_SIZE]) -> CO2Result {
51+
let mut res: [u8; PACKET_SIZE] = [
52+
(buf[3] << 5) | (buf[2] >> 3),
53+
(buf[2] << 5) | (buf[4] >> 3),
54+
(buf[4] << 5) | (buf[0] >> 3),
55+
(buf[0] << 5) | (buf[7] >> 3),
56+
(buf[7] << 5) | (buf[1] >> 3),
57+
(buf[1] << 5) | (buf[6] >> 3),
58+
(buf[6] << 5) | (buf[5] >> 3),
59+
(buf[5] << 5) | (buf[3] >> 3)
60+
];
61+
62+
let magic_word = b"Htemp99e";
63+
for i in 0..PACKET_SIZE {
64+
let sub_val:u8 = (magic_word[i] << 4) | (magic_word[i] >> 4);
65+
res[i] = u8::overflowing_sub(res[i], sub_val).0;
66+
}
67+
68+
if res[4] != 0x0d {
69+
return CO2Result::Error("Unexpected data (data[4] != 0x0d)");
70+
}
71+
let checksum = u8::overflowing_add(
72+
u8::overflowing_add(res[0], res[1]).0, res[2]).0;
73+
if checksum != res[3] {
74+
return CO2Result::Error("Checksum error");
75+
}
76+
77+
let val: u16 = ((res[1] as u16) << 8) + res[2] as u16;
78+
match res[0] {
79+
CODE_TEMPERATURE => CO2Result::Temperature(decode_temperature(val)),
80+
CODE_CONCENTRATION => {
81+
if val > 3000 {
82+
CO2Result::Error(
83+
"Concentration bigger than 3000 (uninitialized device?)")
84+
} else {
85+
CO2Result::Concentration(val)
86+
}
87+
},
88+
_ => CO2Result::Unknown(res[0], val),
89+
}
90+
}
91+
92+
fn open_device(api: &HidApi) -> HidDevice {
93+
loop {
94+
match api.open(DEV_VID, DEV_PID) {
95+
Ok(dev) => return dev,
96+
Err(err) => {
97+
println!("{}", err);
98+
sleep(Duration::from_secs(RETRY_SEC));
99+
},
100+
}
101+
}
102+
}
103+
104+
fn main() {
105+
let api = HidApi::new().expect("HID API object creation failed");
106+
107+
let dev = open_device(&api);
108+
109+
dev.send_feature_report(&[0; PACKET_SIZE]).expect("Feature report failed");
110+
111+
println!("Manufacurer:\t{}", dev.get_manufacturer_string()
112+
.expect("Failed to read manufacurer string"));
113+
println!("Product:\t{}", dev.get_product_string()
114+
.expect("Failed to read product string"));
115+
println!("Serial number:\t{}", dev.get_serial_number_string()
116+
.expect("Failed to read serial number"));
117+
118+
loop {
119+
let mut buf = [0; PACKET_SIZE];
120+
match dev.read_timeout(&mut buf[..], HID_TIMEOUT) {
121+
Ok(PACKET_SIZE) => (),
122+
Ok(res) => {
123+
println!("Error: unexpected length of data: {}/{}",
124+
res, PACKET_SIZE);
125+
continue;
126+
},
127+
Err(err) => {
128+
println!("Error: {:}", err);
129+
sleep(Duration::from_secs(RETRY_SEC));
130+
continue;
131+
}
132+
}
133+
match decode_buf(buf) {
134+
CO2Result::Temperature(val) => println!("Temp:\t{:?}", val),
135+
CO2Result::Concentration(val) => println!("Conc:\t{:?}", val),
136+
CO2Result::Unknown(..) => (),
137+
CO2Result::Error(val) => {
138+
println!("Error:\t{}", val);
139+
sleep(Duration::from_secs(RETRY_SEC));
140+
},
141+
}
142+
}
143+
}

examples/lshid.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,11 @@ extern crate hidapi;
2525
use hidapi::HidApi;
2626

2727
fn main() {
28-
2928
println!("Printing all available hid devices.");
3029

3130
let api = HidApi::new().unwrap();
3231

33-
let devices = api.devices();
34-
35-
for device in &devices {
32+
for device in &api.devices() {
3633
println!("{:#?}", device);
3734
}
38-
39-
println!("");
40-
4135
}

examples/readhid.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ use hidapi::HidApi;
2828

2929
fn main() {
3030

31-
let api = HidApi::new().unwrap();
31+
let api = HidApi::new().expect("Failed to create API instance");
3232

33-
let mut joystick = api.open(1103, 45320).unwrap();
33+
let joystick = api.open(1103, 45320).expect("Failed to open device");
3434

3535
loop {
36-
let data = joystick.read().unwrap();
36+
let mut buf = [0u8; 256];
37+
let res = joystick.read(&mut buf[..]).unwrap();
3738

3839
let mut data_string = String::new();
3940

40-
for u in data {
41+
for u in &buf[..res] {
4142
data_string.push_str(&(u.to_string() + "\t"));
4243
}
4344

0 commit comments

Comments
 (0)