├── .gitignore ├── Cargo.toml ├── README.md └── src ├── demo.rs ├── ffi.rs └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | /.idea -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtlsdr" 3 | version = "0.1.4" 4 | edition = "2024" 5 | authors = ["Adam Greig "] 6 | description = "Rust bindings for librtlsdr" 7 | repository = "https://github.com/adamgreig/rtlsdr-rs" 8 | homepage = "https://github.com/adamgreig/rtlsdr-rs" 9 | readme = "README.md" 10 | keywords = ["SDR", "ffi", "rtlsdr"] 11 | license = "MIT" 12 | 13 | [lib] 14 | name = "rtlsdr" 15 | path = "src/lib.rs" 16 | test = false 17 | doctest = false 18 | bench = false 19 | doc = true 20 | plugin = false 21 | 22 | [[bin]] 23 | name = "rtlsdr_demo" 24 | path = "src/demo.rs" 25 | test = false 26 | doctest = false 27 | bench = false 28 | doc = false 29 | 30 | [dependencies] 31 | libc = "0.2" 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rtlsdr-rs 2 | Rust bindings for librtlsdr 3 | -------------------------------------------------------------------------------- /src/demo.rs: -------------------------------------------------------------------------------- 1 | // Demonstration of the RTL-SDR crate 2 | // Copyright Adam Greig 2014 3 | // Licensed under MIT license 4 | 5 | extern crate rtlsdr; 6 | 7 | use std::fs::File; 8 | use std::path::Path; 9 | use std::io::prelude::*; 10 | 11 | fn main() { 12 | let count = rtlsdr::get_device_count(); 13 | println!("Found {} device(s)", count); 14 | 15 | for index in 0..count { 16 | println!("Index {}:", index); 17 | 18 | let name = rtlsdr::get_device_name(index); 19 | println!(" Name: {}", name); 20 | 21 | let strs = rtlsdr::get_device_usb_strings(index).unwrap(); 22 | println!(" Manufacturer: {}", strs.manufacturer); 23 | println!(" Product: {}", strs.product); 24 | println!(" Serial: {}", strs.serial); 25 | println!(""); 26 | 27 | let idx2 = rtlsdr::get_index_by_serial(strs.serial).unwrap(); 28 | println!(" Index looked up by serial: {}", idx2); 29 | 30 | println!(" Opening device..."); 31 | let mut dev = rtlsdr::open(index).unwrap(); 32 | println!(""); 33 | 34 | println!(" Getting USB strings from opened device..."); 35 | let strs2 = dev.get_usb_strings().unwrap(); 36 | println!(" Manufacturer: {}", strs2.manufacturer); 37 | println!(" Product: {}", strs2.product); 38 | println!(" Serial: {}", strs2.serial); 39 | println!(""); 40 | 41 | let (rtl_freq, tuner_freq) = dev.get_xtal_freq().unwrap(); 42 | println!(" RTL clock freq: {}Hz", rtl_freq); 43 | println!(" Tuner clock freq: {}Hz", tuner_freq); 44 | 45 | println!(" Setting RTL and tuner clock frequencies to same..."); 46 | dev.set_xtal_freq(rtl_freq, tuner_freq).unwrap(); 47 | 48 | println!(" Setting centre frequency to 434MHz..."); 49 | dev.set_center_freq(434_000_000).unwrap(); 50 | 51 | let cfreq = dev.get_center_freq().unwrap(); 52 | println!(" Read current centre frequency: {}Hz", cfreq); 53 | 54 | let ppm = dev.get_freq_correction(); 55 | println!(" Current freq correction: {}ppm", ppm); 56 | 57 | println!(" Setting freq correction to 1ppm..."); 58 | dev.set_freq_correction(1).unwrap(); 59 | 60 | let (t_id, t_name) = dev.get_tuner_type(); 61 | println!(" Tuner is a {} (id {})", &t_name, &t_id); 62 | 63 | //println!(" Setting gain to manual..."); 64 | //dev.set_tuner_gain_mode(true).unwrap(); 65 | 66 | let gains = dev.get_tuner_gains().unwrap(); 67 | println!(" Available gains: {:?}", &gains); 68 | 69 | //println!(" Setting gain to second option {}dB", 70 | //(gains[1] as f64)/10.0f64); 71 | //dev.set_tuner_gain(gains[1]).unwrap(); 72 | 73 | //let gain = dev.get_tuner_gain(); 74 | //println!(" Current gain: {}dB", (gain as f64)/10.0f64); 75 | 76 | println!(" Setting sample rate to 24kHz..."); 77 | dev.set_sample_rate(24000).unwrap(); 78 | 79 | let rate = dev.get_sample_rate().unwrap(); 80 | println!(" Current sample rate: {}Hz", rate); 81 | 82 | //println!(" Setting test mode off..."); 83 | //dev.set_test_mode(false).unwrap(); 84 | 85 | //println!(" Setting AGC off..."); 86 | //dev.set_agc_mode(false).unwrap(); 87 | 88 | //println!(" Disabling direct sampling"); 89 | //dev.set_direct_sampling(rtlsdr::DirectSampling::Disabled).unwrap(); 90 | 91 | let m = dev.get_direct_sampling().unwrap(); 92 | println!(" Direct sampling mode: {:?}", m); 93 | 94 | dev.reset_buffer().unwrap(); 95 | 96 | let data = dev.read_sync(131072).unwrap(); 97 | 98 | let mut file = File::create(&Path::new("data.bin")).unwrap(); 99 | file.write(&data).unwrap(); 100 | 101 | println!(" Closing device..."); 102 | dev.close().unwrap(); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/ffi.rs: -------------------------------------------------------------------------------- 1 | // FFI bindings to rtl-sdr.h (librtlsdr) 2 | // Copyright Adam Greig 2014 3 | // Licensed under MIT license 4 | 5 | use libc::{c_void, c_int, c_char, c_uchar}; 6 | 7 | // rtlsdr_tuner enum 8 | pub const RTLSDR_TUNER_UNKNOWN: c_int = 0; 9 | pub const RTLSDR_TUNER_E4000: c_int = 1; 10 | pub const RTLSDR_TUNER_FC0012: c_int = 2; 11 | pub const RTLSDR_TUNER_FC0013: c_int = 3; 12 | pub const RTLSDR_TUNER_FC2580: c_int = 4; 13 | pub const RTLSDR_TUNER_R820T: c_int = 5; 14 | pub const RTLSDR_TUNER_R828D: c_int = 6; 15 | 16 | #[allow(non_camel_case_types)] 17 | pub enum rtlsdr_dev {} 18 | 19 | #[link(name="rtlsdr")] 20 | unsafe extern "C" { 21 | pub fn rtlsdr_get_device_count() -> u32; 22 | pub fn rtlsdr_get_device_name(index: u32) -> *const c_char; 23 | 24 | // String buffers must be 256 bytes 25 | // Returns 0 on success. 26 | pub fn rtlsdr_get_device_usb_strings( 27 | index: u32, manufact: *mut c_char, 28 | product: *mut c_char, serial: *mut c_char) -> c_int; 29 | 30 | // Returns the index of the first matching device on success, -1 if name is 31 | // NULL, -2 if no devices found, -3 if no matching devices found 32 | pub fn rtlsdr_get_index_by_serial(serial: *const c_char) -> c_int; 33 | 34 | pub fn rtlsdr_open(dev: *mut *mut rtlsdr_dev, index: u32) -> c_int; 35 | pub fn rtlsdr_close(dev: *mut rtlsdr_dev) -> c_int; 36 | 37 | // rtl_freq and tuner_freq in Hz 38 | // Returns 0 on success. 39 | pub fn rtlsdr_set_xtal_freq(dev: *mut rtlsdr_dev, rtl_freq: u32, 40 | tuner_freq: u32) -> c_int; 41 | 42 | // rtl_freq and tuner_freq in Hz 43 | // Returns 0 on success. 44 | pub fn rtlsdr_get_xtal_freq(dev: *mut rtlsdr_dev, rtl_freq: *mut u32, 45 | tuner_freq: *mut u32) -> c_int; 46 | 47 | // String buffers must be 256 bytes 48 | // Returns 0 on success. 49 | pub fn rtlsdr_get_usb_strings(dev: *mut rtlsdr_dev, manufact: *mut c_char, 50 | product: *mut c_char, serial: *mut c_char) 51 | -> c_int; 52 | 53 | // Returns 0 on success, -1 if device handle invalid, -2 if EEPROM size is 54 | // exceeded, -3 if no EEPROM was found 55 | pub fn rtlsdr_write_eeprom(dev: *mut rtlsdr_dev, data: *mut u8, 56 | offset: u8, len: u16) -> c_int; 57 | 58 | // Returns 0 on success, -1 if device handle invalid, -2 if EEPROM size is 59 | // exceeded, -3 if no EEPROM was found 60 | pub fn rtlsdr_read_eeprom(dev: *mut rtlsdr_dev, data: *mut u8, 61 | offset: u8, len: u16) -> c_int; 62 | 63 | pub fn rtlsdr_set_center_freq(dev: *mut rtlsdr_dev, freq: u32) 64 | -> c_int; 65 | 66 | // Returns frequency in Hz (or 0 on error) 67 | pub fn rtlsdr_get_center_freq(dev: *mut rtlsdr_dev) -> u32; 68 | 69 | // Returns 0 on success 70 | pub fn rtlsdr_set_freq_correction(dev: *mut rtlsdr_dev, ppm: c_int) 71 | -> c_int; 72 | 73 | // Return correction value in ppm 74 | pub fn rtlsdr_get_freq_correction(dev: *mut rtlsdr_dev) -> c_int; 75 | 76 | // Returns an rtlsdr_tuner enum 77 | pub fn rtlsdr_get_tuner_type(dev: *mut rtlsdr_dev) -> c_int; 78 | 79 | // Call with `gains=NULL` to return length of `gains`, then allocate and 80 | // call again to have `gains` populated. 81 | // Returns number of available gains (<=0 on error) 82 | pub fn rtlsdr_get_tuner_gains(dev: *mut rtlsdr_dev, gains: *mut c_int) 83 | -> c_int; 84 | 85 | // Returns 0 on success 86 | pub fn rtlsdr_set_tuner_gain(dev: *mut rtlsdr_dev, gain: c_int) -> c_int; 87 | 88 | // Returns gain (in tengths of dB) (0 on error) 89 | pub fn rtlsdr_get_tuner_gain(dev: *mut rtlsdr_dev) -> c_int; 90 | 91 | // Returns 0 on sucess 92 | pub fn rtlsdr_set_tuner_if_gain(dev: *mut rtlsdr_dev, stage: c_int, 93 | gain: c_int) -> c_int; 94 | 95 | // Returns 0 on success 96 | pub fn rtlsdr_set_tuner_gain_mode(dev: *mut rtlsdr_dev, manual: c_int) 97 | -> c_int; 98 | 99 | // bw=0 means automatic bandwidth selection 100 | // return 0 on success 101 | pub fn rtlsdr_set_tuner_bandwidth(dev: *mut rtlsdr_dev, bw: u32) -> c_int; 102 | 103 | pub fn rtlsdr_set_sample_rate(dev: *mut rtlsdr_dev, rate: u32) 104 | -> c_int; 105 | 106 | // Returns sample rate in Hz (0 on error) 107 | pub fn rtlsdr_get_sample_rate(dev: *mut rtlsdr_dev) -> u32; 108 | 109 | // 1 = enable test 110 | // 0 = disable test 111 | // Returns 0 on success 112 | pub fn rtlsdr_set_testmode(dev: *mut rtlsdr_dev, on: c_int) -> c_int; 113 | 114 | // 1 = enable AGC 115 | // 0 = disable AGC 116 | // Returns 0 on success 117 | pub fn rtlsdr_set_agc_mode(dev: *mut rtlsdr_dev, on: c_int) -> c_int; 118 | 119 | // 0 = disable direct sampling 120 | // 1 = I-ADC input enabled 121 | // 2 = Q-ADC input enabled 122 | // Returns 0 on success 123 | pub fn rtlsdr_set_direct_sampling(dev: *mut rtlsdr_dev, on: c_int) 124 | -> c_int; 125 | 126 | // Returns -1 for error, 0 for disabled, 1 for I-ADC, 2 for Q-ADC 127 | pub fn rtlsdr_get_direct_sampling(dev: *mut rtlsdr_dev) -> c_int; 128 | 129 | // 1 = enable offset tuning 130 | // 0 = disable offset tuning 131 | // Returns 0 for success 132 | pub fn rtlsdr_set_offset_tuning(dev: *mut rtlsdr_dev, on: c_int) -> c_int; 133 | 134 | // Returns -1 for error, 0 for disabled, 1 for enabled 135 | pub fn rtlsdr_get_offset_tuning(dev: *mut rtlsdr_dev) -> c_int; 136 | 137 | pub fn rtlsdr_reset_buffer(dev: *mut rtlsdr_dev) -> c_int; 138 | pub fn rtlsdr_read_sync(dev: *mut rtlsdr_dev, buf: *mut c_void, len: c_int, 139 | n_read: *mut c_int) -> c_int; 140 | 141 | // Set `buf_num` to 0 for default of 32 142 | // Set `buf_len` to 0 for default of 16 * 32 * 512 143 | // Returns 0 on success 144 | pub fn rtlsdr_read_async(dev: *mut rtlsdr_dev, 145 | cb: extern fn(*mut c_uchar, 146 | u32, *mut c_void), 147 | buf_num: u32, buf_len: u32) -> c_int; 148 | 149 | // Returns 0 on success 150 | pub fn rtlsdr_cancel_async(dev: *mut rtlsdr_dev) -> c_int; 151 | 152 | } 153 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Rust interface to librtlsdr FFI bindings 2 | // Copyright Adam Greig 2014 3 | // Licensed under MIT license 4 | 5 | #![allow(dead_code)] 6 | 7 | extern crate libc; 8 | mod ffi; 9 | 10 | #[derive(Debug)] 11 | pub struct RTLSDRError { 12 | errno: i32, 13 | errstr: String 14 | } 15 | 16 | impl std::fmt::Display for RTLSDRError { 17 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 18 | write!(f, "RTL-SDR error: {} ({})", self.errstr, self.errno) 19 | } 20 | } 21 | 22 | impl std::error::Error for RTLSDRError {} 23 | 24 | fn rtlsdr_error(errno: libc::c_int, errstr: &str) -> RTLSDRError { 25 | RTLSDRError { errno: errno as i32, errstr: errstr.to_string() } 26 | } 27 | 28 | #[derive(Clone, Copy,Debug)] 29 | pub enum DirectSampling { 30 | Disabled, I, Q 31 | } 32 | 33 | pub struct RTLSDRDevice { 34 | ptr: *mut ffi::rtlsdr_dev 35 | } 36 | 37 | impl Drop for RTLSDRDevice { 38 | #[inline(never)] 39 | fn drop(&mut self) { 40 | unsafe { ffi::rtlsdr_close(self.ptr); } 41 | } 42 | } 43 | 44 | /// Get the number of detected RTL-SDR devices. 45 | pub fn get_device_count() -> i32 { 46 | let count = unsafe { ffi::rtlsdr_get_device_count() }; 47 | count as i32 48 | } 49 | 50 | /// Get the name for a specific RTL-SDR device index. 51 | pub fn get_device_name(index: i32) -> String { 52 | let s = unsafe { ffi::rtlsdr_get_device_name(index as u32) }; 53 | let slice = unsafe { std::ffi::CStr::from_ptr(s).to_bytes() }; 54 | std::str::from_utf8(slice).unwrap().to_string() 55 | } 56 | 57 | /// A set of USB strings for an RTL-SDR device. 58 | pub struct USBStrings { 59 | pub manufacturer: String, pub product: String, pub serial: String 60 | } 61 | 62 | /// Get the USB strings for a specific RTL-SDR device index. 63 | pub fn get_device_usb_strings(index: i32) 64 | -> Result { 65 | let mut mn: [libc::c_char; 256] = [0; 256]; 66 | let mut pd: [libc::c_char; 256] = [0; 256]; 67 | let mut sr: [libc::c_char; 256] = [0; 256]; 68 | match unsafe { ffi::rtlsdr_get_device_usb_strings(index as u32, 69 | mn.as_mut_ptr(), 70 | pd.as_mut_ptr(), 71 | sr.as_mut_ptr()) } { 72 | 0 => unsafe { Ok(USBStrings { 73 | manufacturer: std::str::from_utf8( 74 | std::ffi::CStr::from_ptr(mn.as_ptr()).to_bytes()) 75 | .unwrap().to_string(), 76 | product: std::str::from_utf8( 77 | std::ffi::CStr::from_ptr(pd.as_ptr()).to_bytes()) 78 | .unwrap().to_string(), 79 | serial: std::str::from_utf8( 80 | std::ffi::CStr::from_ptr(sr.as_ptr()).to_bytes()) 81 | .unwrap().to_string() 82 | })}, 83 | err => Err(rtlsdr_error(err, "Unknown")) 84 | } 85 | } 86 | 87 | /// Get the index of a specific RTL-SDR by serial number. 88 | pub fn get_index_by_serial(serial: String) -> Result { 89 | let s = std::ffi::CString::new(serial).unwrap(); 90 | match unsafe { ffi::rtlsdr_get_index_by_serial(s.as_ptr()) } { 91 | -1 => Err(rtlsdr_error(-1, "No name provided")), 92 | -2 => Err(rtlsdr_error(-2, "No devices found")), 93 | -3 => Err(rtlsdr_error(-3, "No devices with that name found")), 94 | index => Ok(index as i32) 95 | } 96 | } 97 | 98 | /// Open an RTL-SDR device by index. 99 | /// 100 | /// Returns a Result on an RTLSDRDevice object which exposes further 101 | /// methods. 102 | pub fn open(index: i32) -> Result { 103 | let mut device: RTLSDRDevice = RTLSDRDevice { ptr: std::ptr::null_mut() }; 104 | let idx = index as u32; 105 | match unsafe { ffi::rtlsdr_open(&mut device.ptr, idx) } { 106 | 0 => Ok(device), 107 | err => Err(rtlsdr_error(err, "Unknown")) 108 | } 109 | } 110 | 111 | impl RTLSDRDevice { 112 | /// Close a previously opened RTL-SDR device. 113 | pub fn close(&mut self) -> Result<(), RTLSDRError> { 114 | match unsafe { ffi::rtlsdr_close(self.ptr) } { 115 | 0 => Ok(()), 116 | err => Err(rtlsdr_error(err, "Unknown")) 117 | } 118 | } 119 | 120 | /// Set crystal frequency (in Hz) for an opened device. 121 | /// 122 | /// NOTE: Only do this if you know what you're doing, for instance if you 123 | /// are injecting your own clock signal or correcting for the frequency of 124 | /// the onboard xtal. In general the RTL and the tuner will be fed from the 125 | /// same clock. 126 | pub fn set_xtal_freq(&mut self, rtl_freq: u32, tuner_freq: u32) 127 | -> Result<(), RTLSDRError> { 128 | let rfreq = rtl_freq as u32; 129 | let tfreq = tuner_freq as u32; 130 | match unsafe { ffi::rtlsdr_set_xtal_freq(self.ptr, rfreq, tfreq) } { 131 | 0 => Ok(()), 132 | err => Err(rtlsdr_error(err, "Unknown")) 133 | } 134 | } 135 | 136 | /// Get crystal frequency (in Hz) for an opened device. 137 | /// 138 | /// Returns a tuple of (RTL freq, tuner freq). 139 | pub fn get_xtal_freq(&mut self) 140 | -> Result<(u32, u32), RTLSDRError> { 141 | let mut rtl_freq: u32 = 0; 142 | let mut tuner_freq: u32 = 0; 143 | match unsafe { ffi::rtlsdr_get_xtal_freq(self.ptr, &mut rtl_freq, 144 | &mut tuner_freq) } { 145 | 0 => Ok((rtl_freq as u32, tuner_freq as u32)), 146 | err => Err(rtlsdr_error(err, "Unknown")) 147 | } 148 | } 149 | 150 | /// Get USB strings for an opened device. 151 | pub fn get_usb_strings(&mut self) 152 | -> Result { 153 | let mut mn: [libc::c_char; 256] = [0; 256]; 154 | let mut pd: [libc::c_char; 256] = [0; 256]; 155 | let mut sr: [libc::c_char; 256] = [0; 256]; 156 | match unsafe { ffi::rtlsdr_get_usb_strings(self.ptr, 157 | mn.as_mut_ptr(), 158 | pd.as_mut_ptr(), 159 | sr.as_mut_ptr()) } { 160 | 0 => unsafe { Ok(USBStrings { 161 | manufacturer: std::str::from_utf8( 162 | std::ffi::CStr::from_ptr(mn.as_ptr()).to_bytes()) 163 | .unwrap().to_string(), 164 | product: std::str::from_utf8( 165 | std::ffi::CStr::from_ptr(pd.as_ptr()).to_bytes()) 166 | .unwrap().to_string(), 167 | serial: std::str::from_utf8( 168 | std::ffi::CStr::from_ptr(sr.as_ptr()).to_bytes()) 169 | .unwrap().to_string() 170 | })}, 171 | err => Err(rtlsdr_error(err, "Unknown")) 172 | } 173 | } 174 | 175 | /// Set the RTL-SDR's centre frequency (in Hz). 176 | pub fn set_center_freq(&mut self, frequency: u32) 177 | -> Result<(), RTLSDRError> { 178 | let freq = frequency as u32; 179 | match unsafe { ffi::rtlsdr_set_center_freq(self.ptr, freq)} { 180 | 0 => Ok(()), 181 | err => Err(rtlsdr_error(err, "Unknown")) 182 | } 183 | } 184 | 185 | /// Get the RTL-SDR's center frequency (in Hz). 186 | pub fn get_center_freq(&mut self) -> Result { 187 | match unsafe { ffi::rtlsdr_get_center_freq(self.ptr) } { 188 | 0 => Err(rtlsdr_error(0, "Unknown")), 189 | freq => Ok(freq as u32) 190 | } 191 | } 192 | 193 | /// Set the RTL-SDR's frequency correction (in ppm). 194 | pub fn set_freq_correction(&mut self, ppm: i32) -> Result<(), RTLSDRError> { 195 | let cppm = ppm as libc::c_int; 196 | match unsafe { ffi::rtlsdr_set_freq_correction(self.ptr, cppm) } { 197 | 0 => Ok(()), 198 | err => Err(rtlsdr_error(err, "Unknown")) 199 | } 200 | } 201 | 202 | /// Get the RTL-SDR's current frequency correction (in ppm). 203 | pub fn get_freq_correction(&mut self) -> i32 { 204 | let ppm = unsafe { ffi::rtlsdr_get_freq_correction(self.ptr) }; 205 | ppm as i32 206 | } 207 | 208 | /// Get the RTL-SDR's tuner type. 209 | /// 210 | /// Returns a tuple (id: i32, name: String). 211 | pub fn get_tuner_type(&mut self) -> (i32, String) { 212 | match unsafe { ffi::rtlsdr_get_tuner_type(self.ptr) } { 213 | ffi::RTLSDR_TUNER_E4000 => 214 | (ffi::RTLSDR_TUNER_E4000 as i32, "E4000".to_string()), 215 | ffi::RTLSDR_TUNER_FC0012 => 216 | (ffi::RTLSDR_TUNER_FC0012 as i32, "FC0012".to_string()), 217 | ffi::RTLSDR_TUNER_FC0013 => 218 | (ffi::RTLSDR_TUNER_FC0013 as i32, "FC0013".to_string()), 219 | ffi::RTLSDR_TUNER_FC2580 => 220 | (ffi::RTLSDR_TUNER_FC2580 as i32, "FC2580".to_string()), 221 | ffi::RTLSDR_TUNER_R820T => 222 | (ffi::RTLSDR_TUNER_R820T as i32, "R820T".to_string()), 223 | ffi::RTLSDR_TUNER_R828D => 224 | (ffi::RTLSDR_TUNER_R828D as i32, "R828D".to_string()), 225 | _ => (ffi::RTLSDR_TUNER_UNKNOWN as i32, "Unknown".to_string()) 226 | } 227 | } 228 | 229 | /// Get a Vec of allowable tuner gains. 230 | /// 231 | /// Gains are specified in tenths-of-a-dB. The number of allowable gains 232 | /// depends on the attached hardware. 233 | pub fn get_tuner_gains(&mut self) 234 | -> Result, RTLSDRError> { 235 | use std::vec::Vec; 236 | let null = std::ptr::null_mut(); 237 | let len = unsafe { ffi::rtlsdr_get_tuner_gains(self.ptr, null) }; 238 | if len > 0 { 239 | let mut out: Vec = Vec::with_capacity(len as usize); 240 | unsafe { out.set_len(len as usize) }; 241 | match unsafe { ffi::rtlsdr_get_tuner_gains(self.ptr, 242 | out.as_mut_ptr()) } { 243 | l if l == len => Ok(out.iter().map(|&g| g as i32).collect()), 244 | err => Err(rtlsdr_error(err, "Could not get list of gains")) 245 | } 246 | } else { 247 | Err(rtlsdr_error(len, "Could not get number of gains")) 248 | } 249 | } 250 | 251 | /// Set tuner gain (from list of allowable gains). 252 | pub fn set_tuner_gain(&mut self, gain: i32) -> Result<(), RTLSDRError> { 253 | let g = gain as libc::c_int; 254 | match unsafe { ffi::rtlsdr_set_tuner_gain(self.ptr, g) } { 255 | 0 => Ok(()), 256 | err => Err(rtlsdr_error(err, "Unknown")) 257 | } 258 | } 259 | 260 | /// Get current tuner gain (in tenths of dB) 261 | pub fn get_tuner_gain(&mut self) -> i32 { 262 | let gain = unsafe { ffi::rtlsdr_get_tuner_gain(self.ptr) }; 263 | gain as i32 264 | } 265 | 266 | /// Set tuner IF gain (in tenths of dB). 267 | /// 268 | /// `stage` specifies which intermediate gain stage to set (1-6 for E4000). 269 | pub fn set_tuner_if_gain(&mut self, stage: i32, gain: i32) 270 | -> Result<(), RTLSDRError> { 271 | match unsafe { ffi::rtlsdr_set_tuner_if_gain(self.ptr, 272 | stage as libc::c_int, 273 | gain as libc::c_int) } { 274 | 0 => Ok(()), 275 | err => Err(rtlsdr_error(err, "Unknown")) 276 | } 277 | } 278 | 279 | /// Set automatic or manual gain. 280 | /// 281 | /// Manual gain must be enabled for set_gain to work. 282 | pub fn set_tuner_gain_mode(&mut self, manual: bool) 283 | -> Result<(), RTLSDRError> { 284 | let m: libc::c_int = match manual { true => 1, false => 0 }; 285 | match unsafe { ffi::rtlsdr_set_tuner_gain_mode(self.ptr, m) } { 286 | 0 => Ok(()), 287 | err => Err(rtlsdr_error(err, "Unknown")) 288 | } 289 | } 290 | 291 | /// Set sample rate (in Hz). 292 | pub fn set_sample_rate(&mut self, rate: u32) -> Result<(), RTLSDRError> { 293 | let r = rate as libc::c_uint; 294 | match unsafe { ffi::rtlsdr_set_sample_rate(self.ptr, r) } { 295 | 0 => Ok(()), 296 | err => Err(rtlsdr_error(err, "Unknown")) 297 | } 298 | } 299 | 300 | /// Get current sample rate (in Hz). 301 | pub fn get_sample_rate(&mut self) -> Result { 302 | match unsafe { ffi::rtlsdr_get_sample_rate(self.ptr) } { 303 | 0 => Err(rtlsdr_error(0, "Unknown")), 304 | rate => Ok(rate as u32) 305 | } 306 | } 307 | 308 | /// Set bandwidth (in Hz). 309 | pub fn set_tuner_bandwidth(&mut self, bw: u32) -> Result<(), RTLSDRError> { 310 | let bwc = bw as libc::c_uint; 311 | match unsafe { ffi::rtlsdr_set_tuner_bandwidth(self.ptr, bwc) } { 312 | 0 => Ok(()), 313 | err => Err(rtlsdr_error(err, "Unknown")) 314 | } 315 | } 316 | 317 | /// Set test mode on or off. 318 | /// 319 | /// Test mode turns on an 8 bit counter rather than sampling the radio 320 | /// input. The counter is generated inside the RTL2832. 321 | pub fn set_test_mode(&mut self, enabled: bool) -> Result<(), RTLSDRError> { 322 | let t: libc::c_int = match enabled { true => 1, false => 0 }; 323 | match unsafe { ffi::rtlsdr_set_testmode(self.ptr, t) } { 324 | 0 => Ok(()), 325 | err => Err(rtlsdr_error(err, "Unknown")) 326 | } 327 | } 328 | 329 | /// Set AGC on or off. 330 | /// 331 | /// Enables or disables the internal digital AGC of the RTL2832. 332 | pub fn set_agc_mode(&mut self, enabled: bool) -> Result<(), RTLSDRError> { 333 | let a: libc::c_int = match enabled { true => 1, false => 0 }; 334 | match unsafe { ffi::rtlsdr_set_agc_mode(self.ptr, a) } { 335 | 0 => Ok(()), 336 | err => Err(rtlsdr_error(err, "Unknown")) 337 | } 338 | } 339 | 340 | /// Set direct sampling. 341 | /// 342 | /// When enabled, the IF mode of the RTL2832 is activated, and 343 | /// set_center_freq will control the IF frequency, allowing tuning from 0 344 | /// to 28.8MHz. 345 | pub fn set_direct_sampling(&mut self, mode: DirectSampling) 346 | -> Result<(), RTLSDRError> { 347 | let m: libc::c_int = match mode { 348 | DirectSampling::Disabled => 0, 349 | DirectSampling::I => 1, 350 | DirectSampling::Q => 2 351 | }; 352 | 353 | match unsafe { ffi::rtlsdr_set_direct_sampling(self.ptr, m) } { 354 | 0 => Ok(()), 355 | err => Err(rtlsdr_error(err, "Unknown")) 356 | } 357 | } 358 | 359 | /// Get current direct sampling mode. 360 | pub fn get_direct_sampling(&mut self) 361 | -> Result { 362 | match unsafe { ffi::rtlsdr_get_direct_sampling(self.ptr) } { 363 | 0 => Ok(DirectSampling::Disabled), 364 | 1 => Ok(DirectSampling::I), 365 | 2 => Ok(DirectSampling::Q), 366 | err => Err(rtlsdr_error(err, "Unknown")), 367 | } 368 | } 369 | 370 | /// Set offset tuning mode on/off. Only use on zero IF tuners. 371 | /// 372 | /// Useful to avoid DC offsets and 1/f noise. 373 | pub fn set_offset_tuning(&mut self, enabled: bool) 374 | -> Result<(), RTLSDRError> { 375 | let e: libc::c_int = match enabled { true => 1, false => 0 }; 376 | match unsafe { ffi::rtlsdr_set_offset_tuning(self.ptr, e) } { 377 | 0 => Ok(()), 378 | err => Err(rtlsdr_error(err, "Unknown")) 379 | } 380 | } 381 | 382 | /// Get current offset tuning status. 383 | pub fn get_offset_tuning(&mut self) -> Result { 384 | match unsafe { ffi::rtlsdr_get_offset_tuning(self.ptr) } { 385 | 0 => Ok(false), 386 | 1 => Ok(true), 387 | err => Err(rtlsdr_error(err, "Unknown")) 388 | } 389 | } 390 | 391 | /// Reset streaming buffer. 392 | pub fn reset_buffer(&mut self) -> Result<(), RTLSDRError> { 393 | match unsafe { ffi::rtlsdr_reset_buffer(self.ptr) } { 394 | 0 => Ok(()), 395 | err => Err(rtlsdr_error(err, "Unknown")) 396 | } 397 | } 398 | 399 | /// Read a buffer synchronously. 400 | pub fn read_sync(&mut self, len: usize) 401 | -> Result, RTLSDRError> { 402 | use std::vec::Vec; 403 | let mut v: Vec = Vec::with_capacity(len); 404 | let mut n: libc::c_int = 0; 405 | let ptr: *mut libc::c_void = v.as_mut_ptr() as *mut libc::c_void; 406 | match unsafe { ffi::rtlsdr_read_sync(self.ptr, ptr, len as libc::c_int, 407 | &mut n) } { 408 | 0 => { 409 | unsafe { v.set_len(n as usize) }; 410 | Ok(v) 411 | }, 412 | err => Err(rtlsdr_error(err, "Unknown")) 413 | } 414 | } 415 | } 416 | --------------------------------------------------------------------------------