From f1ca5f3fddc3c3f4b68ce115cb0a68182aeeecba Mon Sep 17 00:00:00 2001 From: Paul Lecuq Date: Sun, 16 Feb 2025 18:43:41 +0100 Subject: [PATCH] add rust code / remove c code --- Cargo.lock | 181 ++------------- Cargo.toml | 11 +- src/lib.rs | 2 +- src/main.rs | 19 +- build.rs => src/old/build.rs | 0 src/{ => old}/pcsensor.c | 0 src/temp.rs | 433 +++++++++++++++++++++++++++++++++++ 7 files changed, 465 insertions(+), 181 deletions(-) rename build.rs => src/old/build.rs (100%) rename src/{ => old}/pcsensor.c (100%) create mode 100644 src/temp.rs diff --git a/Cargo.lock b/Cargo.lock index 0eff9a5..0394a2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,184 +1,33 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - -[[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" +version = 4 [[package]] name = "libc" -version = "0.2.126" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] -name = "memchr" -version = "2.5.0" +name = "libusb-sys" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[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" +checksum = "4c53b6582563d64ad3e692f54ef95239c3ea8069e82c9eb70ca948869a7ad767" 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", "pkg-config", ] [[package]] -name = "shlex" -version = "1.1.0" +name = "pkg-config" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] -name = "unicode-ident" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +name = "sensor" +version = "0.1.0" +dependencies = [ + "libc", + "libusb-sys", +] diff --git a/Cargo.toml b/Cargo.toml index c98728a..28e7735 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,12 +2,13 @@ name = "sensor" version = "0.1.0" edition = "2021" -build = "build.rs" +#build = "build.rs" [dependencies] libc = "0.2" +libusb-sys = "0.2" -[build-dependencies] -cc = { version = "1.0", features = ["parallel"] } -bindgen = { version = "0.59", default-features = false} -pkg-config = "0.3" +#[build-dependencies] +#cc = { version = "1.0", features = ["parallel"] } +#bindgen = { version = "0.59", default-features = false} +#pkg-config = "0.3" diff --git a/src/lib.rs b/src/lib.rs index a38a13a..0c89d04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,4 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +//include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/src/main.rs b/src/main.rs index 11fd82a..95a019a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,14 @@ -use libc; +pub mod temp; -#[link(name = "pcsensor")] -#[link(name = "usb-1.0")] -extern "C" { - fn get_temp_c() -> libc::c_float; -} +use temp::*; + +//#[link(name = "pcsensor")] +//#[link(name = "usb-1.0")] +//extern "C" { +// fn get_temp_c() -> libc::c_float; +//} fn main() { - unsafe { - println!("{}", get_temp_c()); - } + let temp = get_temp_r(); + println!("{}", temp); } diff --git a/build.rs b/src/old/build.rs similarity index 100% rename from build.rs rename to src/old/build.rs diff --git a/src/pcsensor.c b/src/old/pcsensor.c similarity index 100% rename from src/pcsensor.c rename to src/old/pcsensor.c diff --git a/src/temp.rs b/src/temp.rs new file mode 100644 index 0000000..fb13c01 --- /dev/null +++ b/src/temp.rs @@ -0,0 +1,433 @@ +use std::ffi::*; + +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 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, + }, //decode_answer_fm75}, // 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, + }, //decode_answer_fm75}, // 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 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 {} + +#[derive(Clone)] +pub struct TemperDevice { + handle: *mut *mut libusb_device_handle, + t: TemperType, +} + +impl Copy for TemperDevice {} + +pub struct Device(*mut libusb_device); + +unsafe impl Send for Device {} + +unsafe impl Sync for Device {} + +impl From<*mut libusb_device> for Device { + fn from(value: *mut libusb_device) -> Self { + Self(value) + } +} + +impl Default for TemperDevice { + fn default() -> Self { + Self { + handle: std::ptr::null_mut(), + t: TemperType::default(), + } + } +} + +impl TemperType { + 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]; + } + pub fn decode_func() {} +} + +pub fn usb_detach(lvr_winusb: *mut libusb_device_handle, iInterface: i32) { + let ret; + + unsafe { + ret = libusb_detach_kernel_driver(lvr_winusb, iInterface); + } + if ret == LIBUSB_ERROR_NOT_FOUND { + if DEBUG { + println!("Device already detached"); + } + } +} + +pub fn find_lvr_winusb(ctx: *mut *mut libusb_context, devices: &mut Vec) -> isize { + let mut devs_raw: *const *mut libusb_device = std::ptr::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 = &*std::ptr::slice_from_raw_parts(devs_raw, cnt); + } + let devs: &mut [*mut libusb_device; 16] = &mut [std::ptr::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 { + 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, + }; + + 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 = std::ptr::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 std::mem::MaybeUninit<*mut libusb_context>, + devices: &mut Vec, +) -> isize { + let mut numdev = 0isize; + let ctx = ctx.as_mut_ptr(); + + 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 std::mem::MaybeUninit<*mut libusb_context>, + devices: &mut Vec, +) { + 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.as_mut_ptr()); + } +} + +pub fn get_temp_r() -> f32 { + let mut ctx = std::mem::MaybeUninit::<*mut libusb_context>::uninit(); + 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 devices: Vec = vec![]; + setup_libusb_access(&mut ctx, &mut devices); + + if DEBUG { + println!("control"); + println!("{:?}", devices[0].t); + } + control_transfer(&mut devices[0], &mut UTEMPERATURE); + interrupt_read(&mut devices[0], &mut answer); + devices[0] + .t + .decode_answer_fm75(&answer, &mut tempd, calibration); + cleanup_usb_devices(&mut ctx, &mut devices); + + return tempd[0]; +}