From c430b4b2f5467a0b86d2312f742e5b4ece4f4bad Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Fri, 16 Apr 2021 23:56:40 +0300 Subject: Cleanup deinit and document lifecycle --- README.md | 17 +++++++++++- src/devices/fc0013.rs | 56 --------------------------------------- src/devices/mod.rs | 20 -------------- src/devices/r820t.rs | 73 --------------------------------------------------- src/lib.rs | 36 +++++++++++-------------- src/tuners/fc0013.rs | 56 +++++++++++++++++++++++++++++++++++++++ src/tuners/mod.rs | 20 ++++++++++++++ src/tuners/r820t.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/usb.rs | 33 ++++++++++++++++------- 9 files changed, 205 insertions(+), 179 deletions(-) delete mode 100644 src/devices/fc0013.rs delete mode 100644 src/devices/mod.rs delete mode 100644 src/devices/r820t.rs create mode 100644 src/tuners/fc0013.rs create mode 100644 src/tuners/mod.rs create mode 100644 src/tuners/r820t.rs diff --git a/README.md b/README.md index 94e1af1..c114db7 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,22 @@ Since there isn't (?) any good USB device mocking setup, for tests to pass an RT ## Design -Similarly to the original rtl-sdr driver, we use libusb via the `rusb` bindings as the main interface to issue commands to the rtl-sdr USB dongle. +### Overview + +RusTL-SDR is very similar to the original rtl-sdr driver. It uses libusb, via the [rusb](https://github.com/a1ien/rusb/) bindings, as the main interface to issue commands to the rtl-sdr USB dongle. + +### Lifecycle + +Devices generally go through the following lifecycle: + +1. Get a libusb context/handle, and find a compatible and supported RTL-SDR device +2. Initialize the device baseband +3. Probe the device for known tuners via the I2C interface +4. Run any special initialization required for the detected tuner +5. Interact with the device, usually this is where samples are read +6. Deinitialize the tuner +7. Deinitialize the baseband +8. Close the USB handle ## License diff --git a/src/devices/fc0013.rs b/src/devices/fc0013.rs deleted file mode 100644 index 9eb03f4..0000000 --- a/src/devices/fc0013.rs +++ /dev/null @@ -1,56 +0,0 @@ -use super::{Tuner, TunerInfo}; -use usb::RtlSdrDeviceHandle; - -pub struct FC0013<'a> { - pub device: TunerInfo, - pub handle: &'a RtlSdrDeviceHandle, -} - -pub const TUNER_ID: &str = "fc0013"; - -pub const TUNER_INFO: TunerInfo = TunerInfo { - id: TUNER_ID, - name: "Fitipower FC0013", - i2c_addr: 0xc6, - check_addr: 0x00, - check_val: 0xa3, -}; - -impl<'a> FC0013<'a> { - pub fn new(handle: &'a RtlSdrDeviceHandle) -> FC0013<'a> { - FC0013 { - device: TUNER_INFO, - handle: handle, - } - } -} - -impl<'a> Tuner for FC0013<'a> { - fn init(&self) { - println!("Init {}", self.device.name); - } - - fn exit(&self) { - unimplemented!() - } - - fn set_freq(&self, _freq: u32) { - unimplemented!() - } - - fn set_bw(&self, _bw: u32) { - unimplemented!() - } - - fn set_gain(&self, _gain: u32) { - unimplemented!() - } - - fn set_if_gain(&self, _if_gain: u32) { - unimplemented!() - } - - fn set_gain_mode(&self, _mode: bool) { - unimplemented!() - } -} diff --git a/src/devices/mod.rs b/src/devices/mod.rs deleted file mode 100644 index cbd7edf..0000000 --- a/src/devices/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -pub mod fc0013; -pub mod r820t; - -pub struct TunerInfo { - pub id: &'static str, - pub name: &'static str, - pub i2c_addr: u8, - pub check_addr: u8, - pub check_val: u8, -} - -pub trait Tuner { - fn init(&self); - fn exit(&self); - fn set_freq(&self, freq: u32); - fn set_bw(&self, bw: u32); - fn set_gain(&self, gain: u32); - fn set_if_gain(&self, if_gain: u32); - fn set_gain_mode(&self, mode: bool); -} diff --git a/src/devices/r820t.rs b/src/devices/r820t.rs deleted file mode 100644 index ec0f173..0000000 --- a/src/devices/r820t.rs +++ /dev/null @@ -1,73 +0,0 @@ -use super::{Tuner, TunerInfo}; -use usb::RtlSdrDeviceHandle; - -const R82XX_IF_FREQ: u32 = 3570000; - -pub struct R820T<'a> { - pub device: TunerInfo, - pub handle: &'a RtlSdrDeviceHandle, -} - -pub const TUNER_ID: &str = "r820t"; - -pub const TUNER_INFO: TunerInfo = TunerInfo { - id: TUNER_ID, - name: "Rafael Micro R820T", - i2c_addr: 0x34, - check_addr: 0x00, - check_val: 0x69, -}; - -impl<'a> R820T<'a> { - pub fn new(handle: &'a RtlSdrDeviceHandle) -> R820T<'a> { - R820T { - device: TUNER_INFO, - handle: handle, - } - } -} - -impl<'a> Drop for R820T<'a> { - fn drop(&mut self) {} -} - -impl<'a> Tuner for R820T<'a> { - fn init(&self) { - // disable Zero-IF mode - self.handle.demod_write_reg(1, 0xb1, 0x1a, 1); - - // only enable In-phase ADC input - self.handle.demod_write_reg(0, 0x08, 0x4d, 1); - - // the R82XX use 3.57 MHz IF for the DVB-T 6 MHz mode, and - // 4.57 MHz for the 8 MHz mode - self.handle.set_if_freq(R82XX_IF_FREQ); - - // enable spectrum inversion - self.handle.demod_write_reg(1, 0x15, 0x01, 1); - } - - fn exit(&self) { - unimplemented!() - } - - fn set_freq(&self, _freq: u32) { - unimplemented!() - } - - fn set_bw(&self, _bw: u32) { - unimplemented!() - } - - fn set_gain(&self, _gain: u32) { - unimplemented!() - } - - fn set_if_gain(&self, _if_gain: u32) { - unimplemented!() - } - - fn set_gain_mode(&self, _mode: bool) { - unimplemented!() - } -} diff --git a/src/lib.rs b/src/lib.rs index d068e57..b350616 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,9 @@ extern crate rusb; -mod devices; +mod tuners; mod usb; -use devices::*; +use tuners::*; use usb::RtlSdrDeviceHandle; const INTERFACE_ID: u8 = 0; @@ -51,28 +51,24 @@ impl RtlSdr { handle.init_baseband(); handle.set_i2c_repeater(true); - let tuner: Box = match self.search_tuner(&handle) { - Some(tuner) => match tuner { - r820t::TUNER_ID => Box::new(r820t::R820T::new(&handle)), - fc0013::TUNER_ID => Box::new(fc0013::FC0013::new(&handle)), - _ => { + { + let tuner: Box = match self.search_tuner(&handle) { + Some(tuner) => match tuner { + r820t::TUNER_ID => Box::new(r820t::R820T::new(&handle)), + fc0013::TUNER_ID => Box::new(fc0013::FC0013::new(&handle)), + _ => { + println!("No valid tuner found"); + return; + } + }, + None => { println!("No valid tuner found"); return; } - }, - None => { - println!("No valid tuner found"); - return; - } - }; + }; - tuner.init(); - - // handle.deinit_baseband(); - - // if kernel_driver_attached { - // handle.attach_kernel_driver(); - // } + tuner.init(); + } } else { println!("No match for vid {} and pid {}", vid, pid); } diff --git a/src/tuners/fc0013.rs b/src/tuners/fc0013.rs new file mode 100644 index 0000000..9eb03f4 --- /dev/null +++ b/src/tuners/fc0013.rs @@ -0,0 +1,56 @@ +use super::{Tuner, TunerInfo}; +use usb::RtlSdrDeviceHandle; + +pub struct FC0013<'a> { + pub device: TunerInfo, + pub handle: &'a RtlSdrDeviceHandle, +} + +pub const TUNER_ID: &str = "fc0013"; + +pub const TUNER_INFO: TunerInfo = TunerInfo { + id: TUNER_ID, + name: "Fitipower FC0013", + i2c_addr: 0xc6, + check_addr: 0x00, + check_val: 0xa3, +}; + +impl<'a> FC0013<'a> { + pub fn new(handle: &'a RtlSdrDeviceHandle) -> FC0013<'a> { + FC0013 { + device: TUNER_INFO, + handle: handle, + } + } +} + +impl<'a> Tuner for FC0013<'a> { + fn init(&self) { + println!("Init {}", self.device.name); + } + + fn exit(&self) { + unimplemented!() + } + + fn set_freq(&self, _freq: u32) { + unimplemented!() + } + + fn set_bw(&self, _bw: u32) { + unimplemented!() + } + + fn set_gain(&self, _gain: u32) { + unimplemented!() + } + + fn set_if_gain(&self, _if_gain: u32) { + unimplemented!() + } + + fn set_gain_mode(&self, _mode: bool) { + unimplemented!() + } +} diff --git a/src/tuners/mod.rs b/src/tuners/mod.rs new file mode 100644 index 0000000..cbd7edf --- /dev/null +++ b/src/tuners/mod.rs @@ -0,0 +1,20 @@ +pub mod fc0013; +pub mod r820t; + +pub struct TunerInfo { + pub id: &'static str, + pub name: &'static str, + pub i2c_addr: u8, + pub check_addr: u8, + pub check_val: u8, +} + +pub trait Tuner { + fn init(&self); + fn exit(&self); + fn set_freq(&self, freq: u32); + fn set_bw(&self, bw: u32); + fn set_gain(&self, gain: u32); + fn set_if_gain(&self, if_gain: u32); + fn set_gain_mode(&self, mode: bool); +} diff --git a/src/tuners/r820t.rs b/src/tuners/r820t.rs new file mode 100644 index 0000000..2638917 --- /dev/null +++ b/src/tuners/r820t.rs @@ -0,0 +1,73 @@ +use super::{Tuner, TunerInfo}; +use usb::RtlSdrDeviceHandle; + +const R82XX_IF_FREQ: u32 = 3570000; + +pub struct R820T<'a> { + pub device: TunerInfo, + pub handle: &'a RtlSdrDeviceHandle, +} + +pub const TUNER_ID: &str = "r820t"; + +pub const TUNER_INFO: TunerInfo = TunerInfo { + id: TUNER_ID, + name: "Rafael Micro R820T", + i2c_addr: 0x34, + check_addr: 0x00, + check_val: 0x69, +}; + +impl<'a> R820T<'a> { + pub fn new(handle: &'a RtlSdrDeviceHandle) -> R820T<'a> { + R820T { + device: TUNER_INFO, + handle: handle, + } + } +} + +impl<'a> Drop for R820T<'a> { + fn drop(&mut self) { + self.exit(); + } +} + +impl<'a> Tuner for R820T<'a> { + fn init(&self) { + // disable Zero-IF mode + self.handle.demod_write_reg(1, 0xb1, 0x1a, 1); + + // only enable In-phase ADC input + self.handle.demod_write_reg(0, 0x08, 0x4d, 1); + + // the R82XX use 3.57 MHz IF for the DVB-T 6 MHz mode, and + // 4.57 MHz for the 8 MHz mode + self.handle.set_if_freq(R82XX_IF_FREQ); + + // enable spectrum inversion + self.handle.demod_write_reg(1, 0x15, 0x01, 1); + } + + fn exit(&self) {} + + fn set_freq(&self, _freq: u32) { + unimplemented!() + } + + fn set_bw(&self, _bw: u32) { + unimplemented!() + } + + fn set_gain(&self, _gain: u32) { + unimplemented!() + } + + fn set_if_gain(&self, _if_gain: u32) { + unimplemented!() + } + + fn set_gain_mode(&self, _mode: bool) { + unimplemented!() + } +} diff --git a/src/usb.rs b/src/usb.rs index 92f99d1..0a0003f 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -36,27 +36,37 @@ const CTRL_TIMEOUT: Duration = Duration::from_millis(300); pub struct RtlSdrDeviceHandle { handle: DeviceHandle, iface_id: u8, + kernel_driver_active: bool, } +/// A wrapper around libusb's DeviceHandle that implements +/// various rtl-sdr specific methods impl RtlSdrDeviceHandle { - /// A wrapper around libusb's DeviceHandle that implements - /// various rtl-sdr specific methods pub fn new(handle: DeviceHandle, iface_id: u8) -> RtlSdrDeviceHandle { - RtlSdrDeviceHandle { handle, iface_id } + let mut handle = RtlSdrDeviceHandle { + handle, + iface_id, + kernel_driver_active: false, + }; + handle.detach_kernel_driver(); + handle } - pub fn detach_kernel_driver(&mut self) -> bool { - match self.handle.kernel_driver_active(self.iface_id) { + pub fn detach_kernel_driver(&mut self) { + let active = match self.handle.kernel_driver_active(self.iface_id) { Ok(true) => { self.handle.detach_kernel_driver(self.iface_id).ok(); true } _ => false, - } + }; + self.kernel_driver_active = active; } pub fn attach_kernel_driver(&mut self) { - self.handle.attach_kernel_driver(self.iface_id).ok(); + if self.kernel_driver_active { + self.handle.attach_kernel_driver(self.iface_id).ok(); + } } pub fn claim_interface(&mut self) { @@ -237,9 +247,14 @@ impl RtlSdrDeviceHandle { } pub fn deinit_baseband(&self) { - // deinit tuner? - // power off demod and ADCs self.write_reg(BLOCK_SYSB, ADDR_SYS_DEMOD_CTL, 0x20, 1); } } + +impl Drop for RtlSdrDeviceHandle { + fn drop(&mut self) { + self.deinit_baseband(); + self.attach_kernel_driver(); + } +} -- cgit v1.3.1