Compare commits

..

4 Commits

Author SHA1 Message Date
5ba492b395 code cleanup 2025-02-22 22:20:10 +01:00
b46393984b update TemperType 2025-02-16 22:18:21 +01:00
93552a148f rename 'temp' variable 2025-02-16 18:45:17 +01:00
f1ca5f3fdd add rust code / remove c code 2025-02-16 18:43:41 +01:00
8 changed files with 498 additions and 188 deletions

181
Cargo.lock generated
View File

@ -1,184 +1,33 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[package]]
name = "bindgen"
version = "0.59.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
dependencies = [
"jobserver",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "clang-sys"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b"
dependencies = [
"glob",
"libc",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.126" version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]] [[package]]
name = "memchr" name = "libusb-sys"
version = "2.5.0" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" checksum = "4c53b6582563d64ad3e692f54ef95239c3ea8069e82c9eb70ca948869a7ad767"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
dependencies = [ dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "proc-macro2"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "sensor"
version = "0.1.0"
dependencies = [
"bindgen",
"cc",
"libc", "libc",
"pkg-config", "pkg-config",
] ]
[[package]] [[package]]
name = "shlex" name = "pkg-config"
version = "1.1.0" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]] [[package]]
name = "unicode-ident" name = "sensor"
version = "1.0.2" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" "libc",
"libusb-sys",
]

View File

@ -2,12 +2,13 @@
name = "sensor" name = "sensor"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
build = "build.rs" #build = "build.rs"
[dependencies] [dependencies]
libc = "0.2" libc = "0.2"
libusb-sys = "0.2"
[build-dependencies] #[build-dependencies]
cc = { version = "1.0", features = ["parallel"] } #cc = { version = "1.0", features = ["parallel"] }
bindgen = { version = "0.59", default-features = false} #bindgen = { version = "0.59", default-features = false}
pkg-config = "0.3" #pkg-config = "0.3"

View File

@ -5,23 +5,19 @@
PCSensor temper with Rust and C bindings PCSensor temper with Rust and C bindings
## Dependencies
* libclang-dev
* libusb-1.0-0-dev
## Howto ## Howto
### Dev Run ### Dev Run
``` ```
cargo r cargo run
``` ```
### Build ### Build
```bash ```bash
cargo b -r cargo build --release
``` ```

View File

@ -2,4 +2,4 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs")); //include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

View File

@ -1,13 +1,14 @@
use libc; pub mod temp;
#[link(name = "pcsensor")] use temp::*;
#[link(name = "usb-1.0")]
extern "C" { //#[link(name = "pcsensor")]
fn get_temp_c() -> libc::c_float; //#[link(name = "usb-1.0")]
} //extern "C" {
// fn get_temp_c() -> libc::c_float;
//}
fn main() { fn main() {
unsafe { let temperature = get_temp_r();
println!("{}", get_temp_c()); println!("{}", temperature);
}
} }

463
src/temp.rs Normal file
View File

@ -0,0 +1,463 @@
use std::ffi::CStr;
use std::ptr::{null_mut, slice_from_raw_parts};
use libusb_sys::*;
const MAX_DEV: usize = 8;
const INTERFACE1: i32 = 0x00;
const INTERFACE2: i32 = 0x01;
const REQINTLEN: usize = 8;
const ENDPOINT_INT_IN: u8 = 0x82;
const TIMEOUT: u32 = 5000;
const UTEMPERATURE: &[u8; 8] = &[0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00];
static mut DEBUG: bool = false;
const TEMPER_TYPES: usize = 3;
const TEMPERS: [TemperType; TEMPER_TYPES] = [
TemperType {
vendor_id: 0x0c45,
product_id: 0x7401,
product_name: "TEMPer2",
check_product_name: true,
has_sensor: true,
has_humid: false,
}, // TEMPer2* eg. TEMPer2V1.3
TemperType {
vendor_id: 0x0c45,
product_id: 0x7401,
//product_name: "TEMPer1",
product_name: "TEMPerV1.4",
check_product_name: false,
has_sensor: true,
has_humid: false,
}, // other 0c45:7401 eg. TEMPerV1.4
TemperType {
vendor_id: 0x0c45,
product_id: 0x7402,
product_name: "TEMPerHUM",
check_product_name: false,
has_sensor: true,
has_humid: true,
}, //decode_answer_sht1x},
];
#[derive(Clone, Debug)]
pub struct TemperType {
pub vendor_id: u16,
pub product_id: u16,
pub product_name: &'static str,
pub check_product_name: bool,
pub has_sensor: bool,
pub has_humid: bool,
}
impl TemperType {
pub fn decode(&self, answer: &[u8; 100], tempd: &mut [f32; 2], calibration: &[f32; 2]) {
match self.product_name {
"TEMPer2" => self.decode_answer_fm75(answer, tempd, calibration),
"TEMPerV1.4" => self.decode_answer_fm75(answer, tempd, calibration),
_ => self.decode_answer_fm75(answer, tempd, calibration),
}
}
pub fn decode_answer_fm75(
&self,
answer: &[u8; 100],
tempd: &mut [f32; 2],
calibration: &[f32; 2],
) {
let mut buf: u16;
buf = ((answer[2] as u16) << 8) + ((answer[3] as u16) & 0xFF);
tempd[0] = buf as f32 * (125.0 / 32000.0);
tempd[0] = tempd[0] * calibration[0] + calibration[1];
buf = ((answer[4] as u16) << 8) as u16 + ((answer[5] as u16) & 0xFF) as u16;
tempd[1] = buf as f32 * (125.0 / 32000.0);
tempd[1] = tempd[1] * calibration[0] + calibration[1];
}
}
impl Default for TemperType {
fn default() -> Self {
Self {
vendor_id: 0,
product_id: 0,
product_name: "",
check_product_name: true,
has_sensor: false,
has_humid: false,
}
}
}
impl Copy for TemperType {}
impl std::fmt::Display for TemperType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"vendor_id: {}, product_id: {}, product_name: {}",
self.vendor_id, self.product_id, self.product_name
)
}
}
#[derive(Clone)]
pub struct TemperDevice {
handle: *mut *mut libusb_device_handle,
t: TemperType,
}
impl Copy for TemperDevice {}
impl Default for TemperDevice {
fn default() -> Self {
Self {
handle: null_mut(),
t: TemperType::default(),
}
}
}
impl std::fmt::Display for TemperDevice {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.t)
}
}
pub fn usb_detach(lvr_winusb: *mut libusb_device_handle, i_interface: i32) {
let ret;
unsafe {
ret = libusb_detach_kernel_driver(lvr_winusb, i_interface);
}
if ret == LIBUSB_ERROR_NOT_FOUND {
unsafe {
if DEBUG {
println!("Device already detached");
}
}
}
}
pub fn find_lvr_winusb(ctx: *mut *mut libusb_context, devices: &mut Vec<TemperDevice>) -> isize {
let mut devs_raw: *const *mut libusb_device = null_mut();
let cnt: usize;
unsafe { cnt = libusb_get_device_list(*ctx, &mut devs_raw) as usize };
if cnt < 1 {
println!("Could not find USB device: {}", cnt);
}
let mut i = 0usize;
let mut numdev = 0;
let devs_tmp;
unsafe {
devs_tmp = &*slice_from_raw_parts(devs_raw, cnt);
}
let devs: &mut [*mut libusb_device; 16] = &mut [null_mut(); 16];
for i in 0usize..cnt as usize {
devs[i] = devs_tmp[i];
}
while i < cnt && numdev < MAX_DEV {
let mut desc: libusb_device_descriptor;
/*let mut desc = libusb_device_descriptor {
bLength: 0,
bDescriptorType: 0,
bcdUSB: 0,
bDeviceClass: 0,
bDeviceSubClass: 0,
bDeviceProtocol: 0,
bMaxPacketSize0: 0,
idVendor: 0,
idProduct: 0,
bcdDevice: 0,
iManufacturer: 0,
iProduct: 0,
iSerialNumber: 0,
bNumConfigurations: 0,
};*/
unsafe {
desc = std::mem::zeroed();
}
let s;
unsafe {
s = libusb_get_device_descriptor(
devs[i],
&mut desc as *mut _ as *mut libusb_device_descriptor,
);
}
if s < 0 {
println!("Could not get USB device descriptor: {}", s);
i += 1;
continue;
}
unsafe {
for temper in TEMPERS {
if desc.idVendor == temper.vendor_id && desc.idProduct == temper.product_id {
let bus: u8;
let addr: u8;
let mut descmanu_b: [u8; 100] = [0; 100];
let mut descprod_b: [u8; 100] = [0; 100];
let mut descseri_b: [u8; 100] = [0; 100];
bus = libusb_get_bus_number(devs[i]);
addr = libusb_get_device_address(devs[i]);
let mut handle: *mut libusb_device_handle = null_mut();
let s = libusb_open(devs[i], &mut handle);
if s != 0 {
println!("error open {}", s);
}
libusb_get_string_descriptor_ascii(
handle,
desc.iManufacturer,
descmanu_b.as_mut_ptr(),
256,
);
libusb_get_string_descriptor_ascii(
handle,
desc.iProduct,
descprod_b.as_mut_ptr(),
256,
);
libusb_get_string_descriptor_ascii(
handle,
desc.iSerialNumber,
descseri_b.as_mut_ptr(),
256,
);
let descmanu: &CStr = CStr::from_bytes_until_nul(&descmanu_b).unwrap();
let descprod: &CStr = CStr::from_bytes_until_nul(&descprod_b).unwrap();
let descseri: &CStr = CStr::from_bytes_until_nul(&descseri_b).unwrap();
let mut device = TemperDevice::default();
if temper.check_product_name {
if descprod.to_str().unwrap() == temper.product_name {
device.handle = &mut handle;
device.t = temper;
devices.push(device);
} else {
libusb_close(handle);
continue;
}
} else {
device.handle = &mut handle;
device.t = temper;
devices.push(device);
}
if DEBUG {
println!(
"{} {} {} {} {} {} {}",
bus,
addr,
desc.idVendor,
desc.idProduct,
descmanu.to_str().unwrap(),
descprod.to_str().unwrap(),
descseri.to_str().unwrap()
);
}
numdev += 1;
break;
}
}
}
i += 1;
}
numdev as isize
}
pub fn setup_libusb_access(
ctx: &mut *mut libusb_context,
devices: &mut Vec<TemperDevice>,
) -> isize {
let numdev;
unsafe {
{
let res = libusb_init(ctx);
if res != 0 {
println!("Error code {res}: failed");
return -1;
}
}
numdev = find_lvr_winusb(ctx, devices);
}
if numdev < 1 {
println!("Couldn't find the USB device, Exiting: {}", numdev);
return -1;
}
for device in devices.iter() {
let handle = device.handle;
unsafe {
usb_detach(*handle, INTERFACE1);
usb_detach(*handle, INTERFACE2);
}
let cfg;
unsafe {
libusb_reset_device(*device.handle);
cfg = libusb_set_configuration(*device.handle, 0x01);
}
if cfg < 0 {
println!("Could not set configuration 1");
return -1;
}
let mut s;
unsafe { s = libusb_claim_interface(*device.handle, INTERFACE1) }
if s < 0 {
println!("Could not claim interface. Error: {}", s);
return -1;
}
unsafe { s = libusb_claim_interface(*device.handle, INTERFACE2) }
if s < 0 {
println!("Could not claim interface. Error: {}", s);
return -1;
}
}
numdev as isize
}
#[allow(unused_variables)]
pub fn ini_control_transfer(dev: &mut TemperDevice) {
let r;
let mut question: [u8; REQINTLEN] = [0; REQINTLEN];
question[0] = 0x01;
question[1] = 0x01;
unsafe {
r = libusb_control_transfer(
*dev.handle,
0x21,
0x09,
0x0201,
0x00,
question.as_mut_ptr(),
REQINTLEN as u16,
TIMEOUT,
);
}
if r < 0 {
println!("USB control write")
}
}
#[allow(unused_variables)]
pub fn control_transfer(dev: &mut TemperDevice, pquestion: &[u8; 8]) {
let r;
let mut question = pquestion.clone();
let question: *mut u8 = question.as_mut_ptr();
unsafe {
r = libusb_control_transfer(
*dev.handle,
0x21,
0x09,
0x0200,
0x01,
question,
REQINTLEN as u16,
TIMEOUT,
);
}
if r < 0 {
println!("USB control write")
}
}
pub fn interrupt_read(dev: &mut TemperDevice, data: &mut [u8; 100]) {
let (s, _i): (i32, i32);
let mut transferred: i32 = 0i32;
unsafe {
s = libusb_interrupt_transfer(
*dev.handle,
ENDPOINT_INT_IN,
data.as_mut_ptr(),
REQINTLEN as i32,
&mut transferred,
TIMEOUT,
);
}
if transferred != REQINTLEN as i32 {
println!("USB read failed: {}", s);
}
}
pub fn cleanup_usb_devices(ctx: &mut *mut libusb_context, devices: &mut Vec<TemperDevice>) {
for device in devices {
unsafe {
libusb_release_interface(*device.handle, INTERFACE1);
libusb_release_interface(*device.handle, INTERFACE2);
libusb_close(*device.handle);
}
}
unsafe {
libusb_exit(*ctx);
}
}
pub fn get_temp_r() -> String {
let mut ctx: libusb_context;
unsafe {
ctx = std::mem::zeroed();
}
let mut ctx = &mut ctx as *mut _ as *mut libusb_context;
let mut answer: &mut [u8; 100] = &mut [0; 100];
let mut tempd: &mut [f32; 2] = &mut [0.; 2];
let calibration: &[f32; 2] = &[1., 0.];
let mut results: Vec<String> = vec![];
let output: String;
let mut devices: Vec<TemperDevice> = vec![];
setup_libusb_access(&mut ctx, &mut devices);
for device in devices.iter_mut() {
unsafe {
if DEBUG {
println!("{:?}", device.t);
}
}
control_transfer(device, &UTEMPERATURE);
interrupt_read(device, &mut answer);
device.t.decode(&answer, &mut tempd, calibration);
results.push(format!("{}", tempd[0]));
}
cleanup_usb_devices(&mut ctx, &mut devices);
output = results.join(",");
return output;
}