From fa3ea852003103cdc2df08642cade61e820f9d07 Mon Sep 17 00:00:00 2001 From: Ben Sherriff Date: Wed, 14 Jan 2026 17:31:45 -0500 Subject: [PATCH] temp --- crates/adsb/rust-toolchain.toml | 2 +- crates/adsb/rustfmt.toml | 3 - crates/adsb/src/main.rs | 283 +++++++++++++++++++++++--------- rust-toolchain.toml | 2 +- rustfmt.toml | 3 + 5 files changed, 213 insertions(+), 80 deletions(-) delete mode 100644 crates/adsb/rustfmt.toml diff --git a/crates/adsb/rust-toolchain.toml b/crates/adsb/rust-toolchain.toml index 02d090f..a316e85 100644 --- a/crates/adsb/rust-toolchain.toml +++ b/crates/adsb/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "stable" +channel = "nightly" components = ["rustfmt", "clippy"] \ No newline at end of file diff --git a/crates/adsb/rustfmt.toml b/crates/adsb/rustfmt.toml deleted file mode 100644 index 76f62b4..0000000 --- a/crates/adsb/rustfmt.toml +++ /dev/null @@ -1,3 +0,0 @@ -indent_style = "Block" -reorder_imports = false -tab_spaces = 2 \ No newline at end of file diff --git a/crates/adsb/src/main.rs b/crates/adsb/src/main.rs index d90712a..73dbb4b 100644 --- a/crates/adsb/src/main.rs +++ b/crates/adsb/src/main.rs @@ -1,9 +1,12 @@ +#![feature(extern_types)] + mod constants; mod device; mod error; mod frame; mod hex; +use std::ffi::{c_char, c_int, c_void, CStr}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use crate::device::RtlSdrDevice; @@ -12,87 +15,217 @@ use crate::constants::DEVICE_RTL2832U; use crate::frame::ADSBFrame; use crate::hex::hex_to_bytes; -#[derive(Parser, Debug)] -#[command(author, version, about = "An ADS-B Receiver")] -struct ReceiverArgs { - /// Hex-string to decode - #[arg(short = 'd', long)] - decode: Option, +#[link(name = "rtlsdr")] +unsafe extern "C" { + fn rtlsdr_get_device_count() -> u32; + fn rtlsdr_get_device_name(index: u32) -> *const c_char; + fn rtlsdr_get_device_usb_strings( + index: u32, + manufact: *mut c_char, + product: *mut c_char, + serial: *mut c_char, + ) -> c_int; - /// Connect to the USB device - #[arg(short = 'c', long, action)] - connect: bool, + type rtlsdr_dev_t; - /// Display ADS-B/Mode-S receiver info - #[arg(short = 'i', long, action)] - info: bool, + fn rtlsdr_open(dev: *mut *mut rtlsdr_dev_t, index: u32) -> c_int; + fn rtlsdr_close(dev: *mut rtlsdr_dev_t) -> c_int; - /// Enable debug logging - #[arg(short = 'D', long, action = clap::ArgAction::Count)] - debug: u8, + fn rtlsdr_set_sample_rate(dev: *mut rtlsdr_dev_t, rate: u32) -> c_int; + fn rtlsdr_set_center_freq(dev: *mut rtlsdr_dev_t, freq: u32) -> c_int; + fn rtlsdr_set_agc_mode(dev: *mut rtlsdr_dev_t, on: c_int) -> c_int; + fn rtlsdr_set_tuner_gain_mode(dev: *mut rtlsdr_dev_t, manual: c_int) -> c_int; + fn rtlsdr_reset_buffer(dev: *mut rtlsdr_dev_t) -> c_int; + + fn rtlsdr_read_sync( + dev: *mut rtlsdr_dev_t, + buf: *mut c_void, + len: c_int, + n_read: *mut c_int, + ) -> c_int; +} +struct Device { + ptr: *mut rtlsdr_dev_t, } -fn main() { - let args = ReceiverArgs::parse(); - - let default_filter = match args.debug { - 0 => "warn,adsb=info", // no -D - 1 => "warn,adsb=debug", // -D - _ => "trace,adsb=trace", // -DD or more - }; - - env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", default_filter)); - - let device_info = DEVICE_RTL2832U; - - // Handle connection - if args.connect { - log::info!("Connecting to {:?}", device_info); - let mut device = match RtlSdrDevice::open(device_info.vid, device_info.pid) { - Ok(d) => d, - Err(err) => { - log::error!("Unable to open RTL SDR device: {:?}", err); - return; - } - }; - log::debug!("Connected to {:?}", device_info.to_string()); - - let running = Arc::new(AtomicBool::new(true)); - if let Err(err) = ctrlc::set_handler({ - let running = running.clone(); - move || running.store(false, Ordering::SeqCst) - }) { - log::error!("Error setting Ctrl-C handler: {}", err); - running.store(false, Ordering::SeqCst); - }; - - if let Err(err) = device.process(running) { - log::error!("Failed to read from device: {}", err); - if let Err(err) = device.close() { - log::error!("Failed to close device: {}", err); - }; - }; - } - // Display dongle info - else if args.info { - RtlSdrDevice::info(device_info.vid, device_info.pid); - } - // Handle decode mode - else if let Some(mut hex_string) = args.decode { - if let Some(stripped) = hex_string.strip_prefix("0x") { - hex_string = stripped.to_string(); +impl Device { + fn open(index: u32) -> Result { + let mut dev: *mut rtlsdr_dev_t = std::ptr::null_mut(); + let rc = unsafe { rtlsdr_open(&mut dev as *mut _, index) }; + if rc != 0 { + return Err(format!("Failed to open device: {}", rc)); } - let buffer = match hex_to_bytes(&hex_string) { - Ok(buffer) => buffer, - Err(err) => { - eprintln!("Unable to convert hex to bytes: {:?}", err); - return; - } + Ok(Self { ptr: dev }) + } + + fn set_sample_rate(&mut self, rate: u32) -> Result<(), String> { + let rc = unsafe { rtlsdr_set_sample_rate(self.ptr, rate) }; + if rc != 0 { + return Err(format!("Failed to set sample rate: {}", rc)); + } + Ok(()) + } + + fn set_center_freq(&mut self, freq: u32) -> Result<(), String> { + let rc = unsafe { rtlsdr_set_center_freq(self.ptr, freq) }; + if rc != 0 { + return Err(format!("Failed to set center freq: {}", rc)); + } + Ok(()) + } + + fn set_agc(&mut self, on: bool) -> Result<(), String> { + let rc = unsafe { rtlsdr_set_agc_mode(self.ptr, if on { 1 } else { 0 }) }; + if rc != 0 { + return Err(format!("Failed to set AGC: {}", rc)); + } + Ok(()) + } + + // manual = false -> auto-gain, manual = true -> set a gain + fn set_tuner_gain_mode(&mut self, manual: bool) -> Result<(), String> { + let rc = unsafe { rtlsdr_set_tuner_gain_mode(self.ptr, if manual { 1 } else { 0 }) }; + if rc != 0 { + return Err(format!("Failed to set tuner gain mode: {}", rc)); + } + Ok(()) + } + + fn set_buffer(&mut self) -> Result<(), String> { + let rc = unsafe { rtlsdr_reset_buffer(self.ptr) }; + if rc != 0 { + return Err(format!("Failed to reset buffer: {}", rc)); + } + Ok(()) + } + + // Returns the number of bytes placed in buf (I/Q interleaved, u8 + fn read_sync(&mut self, buf: &mut [u8]) -> Result { + let mut n_read: c_int = 0; + let rc = unsafe { + rtlsdr_read_sync( + self.ptr, + buf.as_mut_ptr() as *mut c_void, + buf.len() as c_int, + &mut n_read as *mut _, + ) }; - if let Ok(frame) = ADSBFrame::decode(&buffer) { - println!("{:?}", frame); - }; - } else { - eprintln!("No connection specified"); + if rc != 0 { + return Err(format!("Failed to read sync: {}", rc)); + } + Ok(n_read as usize) } } + +impl Drop for Device { + fn drop(&mut self) { + if !self.ptr.is_null() { + unsafe { rtlsdr_close(self.ptr) }; + self.ptr = std::ptr::null_mut(); + } + } +} + +fn cstr_from_ptr(ptr: *const c_char) -> String { + if ptr.is_null() { + return String::new(); + } + unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() } +} + +fn main() -> Result<(), Box> { + unsafe { + let count = rtlsdr_get_device_count(); + log::debug!("Found {} devices", count); + for i in 0..count { + let name = cstr_from_ptr(rtlsdr_get_device_name(i)); + log::debug!("Device {}: {}", i, name); + } + } + Ok(()) +} + +// #[derive(Parser, Debug)] +// #[command(author, version, about = "An ADS-B Receiver")] +// struct ReceiverArgs { +// /// Hex-string to decode +// #[arg(short = 'd', long)] +// decode: Option, +// +// /// Connect to the USB device +// #[arg(short = 'c', long, action)] +// connect: bool, +// +// /// Display ADS-B/Mode-S receiver info +// #[arg(short = 'i', long, action)] +// info: bool, +// +// /// Enable debug logging +// #[arg(short = 'D', long, action = clap::ArgAction::Count)] +// debug: u8, +// } +// +// fn main() { +// let args = ReceiverArgs::parse(); +// +// let default_filter = match args.debug { +// 0 => "warn,adsb=info", // no -D +// 1 => "warn,adsb=debug", // -D +// _ => "trace,adsb=trace", // -DD or more +// }; +// +// env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", default_filter)); +// +// let device_info = DEVICE_RTL2832U; +// +// // Handle connection +// if args.connect { +// log::info!("Connecting to {:?}", device_info); +// let mut device = match RtlSdrDevice::open(device_info.vid, device_info.pid) { +// Ok(d) => d, +// Err(err) => { +// log::error!("Unable to open RTL SDR device: {:?}", err); +// return; +// } +// }; +// log::debug!("Connected to {:?}", device_info.to_string()); +// +// let running = Arc::new(AtomicBool::new(true)); +// if let Err(err) = ctrlc::set_handler({ +// let running = running.clone(); +// move || running.store(false, Ordering::SeqCst) +// }) { +// log::error!("Error setting Ctrl-C handler: {}", err); +// running.store(false, Ordering::SeqCst); +// }; +// +// if let Err(err) = device.process(running) { +// log::error!("Failed to read from device: {}", err); +// if let Err(err) = device.close() { +// log::error!("Failed to close device: {}", err); +// }; +// }; +// } +// // Display dongle info +// else if args.info { +// RtlSdrDevice::info(device_info.vid, device_info.pid); +// } +// // Handle decode mode +// else if let Some(mut hex_string) = args.decode { +// if let Some(stripped) = hex_string.strip_prefix("0x") { +// hex_string = stripped.to_string(); +// } +// let buffer = match hex_to_bytes(&hex_string) { +// Ok(buffer) => buffer, +// Err(err) => { +// eprintln!("Unable to convert hex to bytes: {:?}", err); +// return; +// } +// }; +// if let Ok(frame) = ADSBFrame::decode(&buffer) { +// println!("{:?}", frame); +// }; +// } else { +// eprintln!("No connection specified"); +// } +// } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 02d090f..a316e85 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "stable" +channel = "nightly" components = ["rustfmt", "clippy"] \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml index aec2d6e..8ea00f2 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,6 @@ indent_style = "Block" reorder_imports = true +imports_layout = "HorizontalVertical" +imports_granularity = "Crate" +group_imports = "One" tab_spaces = 2 \ No newline at end of file