Skip to main content

rtlsdr_pure/
rtl2832.rs

1use cross_usb::prelude::*;
2use cross_usb::usb::{ControlIn, ControlOut, ControlType, Recipient};
3
4use crate::error::{Error, Result, ResultExt};
5use crate::r82xx::{R82XX_CHECK_ADDR, R82XX_CHECK_VAL, R82XX_IF_FREQ, R82xx, R82xxKind};
6
7pub const DEFAULT_SAMPLE_RATE: u32 = 2_048_000;
8
9const DEF_RTL_XTAL_FREQ: u32 = 28_800_000;
10const DEFAULT_BULK_ENDPOINT: u8 = 0x81;
11const DEFAULT_READ_LENGTH: usize = 16 * 32 * 512;
12
13const E4K_I2C_ADDR: u8 = 0xc8;
14const E4K_CHECK_ADDR: u8 = 0x02;
15const E4K_CHECK_VAL: u8 = 0x40;
16
17const FC0012_I2C_ADDR: u8 = 0xc6;
18const FC0012_CHECK_ADDR: u8 = 0x00;
19const FC0012_CHECK_VAL: u8 = 0xa1;
20
21const FC0013_I2C_ADDR: u8 = 0xc6;
22const FC0013_CHECK_ADDR: u8 = 0x00;
23const FC0013_CHECK_VAL: u8 = 0xa3;
24
25const FC2580_I2C_ADDR: u8 = 0xac;
26const FC2580_CHECK_ADDR: u8 = 0x01;
27const FC2580_CHECK_VAL: u8 = 0x56;
28
29const R820T_I2C_ADDR: u8 = 0x34;
30const R828D_I2C_ADDR: u8 = 0x74;
31const R828D_XTAL_FREQ: u32 = 16_000_000;
32
33const USB_SYSCTL: u16 = 0x2000;
34const USB_EPA_CTL: u16 = 0x2148;
35const USB_EPA_MAXPKT: u16 = 0x2158;
36
37const DEMOD_CTL: u16 = 0x3000;
38const GPO: u16 = 0x3001;
39const GPOE: u16 = 0x3003;
40const GPD: u16 = 0x3004;
41const DEMOD_CTL_1: u16 = 0x300b;
42
43const USBB: u8 = 1;
44const SYSB: u8 = 2;
45const IICB: u8 = 6;
46
47const FIR_DEFAULT: [i16; 16] = [
48    -54, -36, -41, -40, -32, -14, 14, 53, 101, 156, 215, 273, 327, 372, 404, 421,
49];
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub struct KnownDevice {
53    pub vendor_id: u16,
54    pub product_id: u16,
55    pub name: &'static str,
56}
57
58pub const KNOWN_DEVICES: &[KnownDevice] = &[
59    KnownDevice {
60        vendor_id: 0x0bda,
61        product_id: 0x2832,
62        name: "Generic RTL2832U",
63    },
64    KnownDevice {
65        vendor_id: 0x0bda,
66        product_id: 0x2838,
67        name: "Generic RTL2832U OEM",
68    },
69    KnownDevice {
70        vendor_id: 0x0413,
71        product_id: 0x6680,
72        name: "DigitalNow Quad DVB-T PCI-E card",
73    },
74    KnownDevice {
75        vendor_id: 0x0413,
76        product_id: 0x6f0f,
77        name: "Leadtek WinFast DTV Dongle mini D",
78    },
79    KnownDevice {
80        vendor_id: 0x0458,
81        product_id: 0x707f,
82        name: "Genius TVGo DVB-T03 USB dongle (Ver. B)",
83    },
84    KnownDevice {
85        vendor_id: 0x0ccd,
86        product_id: 0x00a9,
87        name: "Terratec Cinergy T Stick Black (rev 1)",
88    },
89    KnownDevice {
90        vendor_id: 0x0ccd,
91        product_id: 0x00b3,
92        name: "Terratec NOXON DAB/DAB+ USB dongle (rev 1)",
93    },
94    KnownDevice {
95        vendor_id: 0x0ccd,
96        product_id: 0x00b4,
97        name: "Terratec Deutschlandradio DAB Stick",
98    },
99    KnownDevice {
100        vendor_id: 0x0ccd,
101        product_id: 0x00b5,
102        name: "Terratec NOXON DAB Stick - Radio Energy",
103    },
104    KnownDevice {
105        vendor_id: 0x0ccd,
106        product_id: 0x00b7,
107        name: "Terratec Media Broadcast DAB Stick",
108    },
109    KnownDevice {
110        vendor_id: 0x0ccd,
111        product_id: 0x00b8,
112        name: "Terratec BR DAB Stick",
113    },
114    KnownDevice {
115        vendor_id: 0x0ccd,
116        product_id: 0x00b9,
117        name: "Terratec WDR DAB Stick",
118    },
119    KnownDevice {
120        vendor_id: 0x0ccd,
121        product_id: 0x00c0,
122        name: "Terratec MuellerVerlag DAB Stick",
123    },
124    KnownDevice {
125        vendor_id: 0x0ccd,
126        product_id: 0x00c6,
127        name: "Terratec Fraunhofer DAB Stick",
128    },
129    KnownDevice {
130        vendor_id: 0x0ccd,
131        product_id: 0x00d3,
132        name: "Terratec Cinergy T Stick RC (Rev.3)",
133    },
134    KnownDevice {
135        vendor_id: 0x0ccd,
136        product_id: 0x00d7,
137        name: "Terratec T Stick PLUS",
138    },
139    KnownDevice {
140        vendor_id: 0x0ccd,
141        product_id: 0x00e0,
142        name: "Terratec NOXON DAB/DAB+ USB dongle (rev 2)",
143    },
144    KnownDevice {
145        vendor_id: 0x1554,
146        product_id: 0x5020,
147        name: "PixelView PV-DT235U(RN)",
148    },
149    KnownDevice {
150        vendor_id: 0x15f4,
151        product_id: 0x0131,
152        name: "Astrometa DVB-T/DVB-T2",
153    },
154    KnownDevice {
155        vendor_id: 0x15f4,
156        product_id: 0x0133,
157        name: "HanfTek DAB+FM+DVB-T",
158    },
159    KnownDevice {
160        vendor_id: 0x185b,
161        product_id: 0x0620,
162        name: "Compro Videomate U620F",
163    },
164    KnownDevice {
165        vendor_id: 0x185b,
166        product_id: 0x0650,
167        name: "Compro Videomate U650F",
168    },
169    KnownDevice {
170        vendor_id: 0x185b,
171        product_id: 0x0680,
172        name: "Compro Videomate U680F",
173    },
174    KnownDevice {
175        vendor_id: 0x1b80,
176        product_id: 0xd393,
177        name: "GIGABYTE GT-U7300",
178    },
179    KnownDevice {
180        vendor_id: 0x1b80,
181        product_id: 0xd394,
182        name: "DIKOM USB-DVBT HD",
183    },
184    KnownDevice {
185        vendor_id: 0x1b80,
186        product_id: 0xd395,
187        name: "Peak 102569AGPK",
188    },
189    KnownDevice {
190        vendor_id: 0x1b80,
191        product_id: 0xd397,
192        name: "KWorld KW-UB450-T USB DVB-T Pico TV",
193    },
194    KnownDevice {
195        vendor_id: 0x1b80,
196        product_id: 0xd398,
197        name: "Zaapa ZT-MINDVBZP",
198    },
199    KnownDevice {
200        vendor_id: 0x1b80,
201        product_id: 0xd39d,
202        name: "SVEON STV20 DVB-T USB & FM",
203    },
204    KnownDevice {
205        vendor_id: 0x1b80,
206        product_id: 0xd3a4,
207        name: "Twintech UT-40",
208    },
209    KnownDevice {
210        vendor_id: 0x1b80,
211        product_id: 0xd3a8,
212        name: "ASUS U3100MINI_PLUS_V2",
213    },
214    KnownDevice {
215        vendor_id: 0x1b80,
216        product_id: 0xd3af,
217        name: "SVEON STV27 DVB-T USB & FM",
218    },
219    KnownDevice {
220        vendor_id: 0x1b80,
221        product_id: 0xd3b0,
222        name: "SVEON STV21 DVB-T USB & FM",
223    },
224    KnownDevice {
225        vendor_id: 0x1d19,
226        product_id: 0x1101,
227        name: "Dexatek DK DVB-T Dongle (Logilink VG0002A)",
228    },
229    KnownDevice {
230        vendor_id: 0x1d19,
231        product_id: 0x1102,
232        name: "Dexatek DK DVB-T Dongle (MSI DigiVox mini II V3.0)",
233    },
234    KnownDevice {
235        vendor_id: 0x1d19,
236        product_id: 0x1103,
237        name: "Dexatek Technology Ltd. DK 5217 DVB-T Dongle",
238    },
239    KnownDevice {
240        vendor_id: 0x1d19,
241        product_id: 0x1104,
242        name: "MSI DigiVox Micro HD",
243    },
244    KnownDevice {
245        vendor_id: 0x1f4d,
246        product_id: 0xa803,
247        name: "Sweex DVB-T USB",
248    },
249    KnownDevice {
250        vendor_id: 0x1f4d,
251        product_id: 0xb803,
252        name: "GTek T803",
253    },
254    KnownDevice {
255        vendor_id: 0x1f4d,
256        product_id: 0xc803,
257        name: "Lifeview LV5TDeluxe",
258    },
259    KnownDevice {
260        vendor_id: 0x1f4d,
261        product_id: 0xd286,
262        name: "MyGica TD312",
263    },
264    KnownDevice {
265        vendor_id: 0x1f4d,
266        product_id: 0xd803,
267        name: "PROlectrix DV107669",
268    },
269];
270
271#[derive(Debug, Clone, PartialEq, Eq)]
272pub struct DeviceDescription {
273    pub vendor_id: u16,
274    pub product_id: u16,
275    pub name: Option<&'static str>,
276    pub manufacturer: Option<String>,
277    pub product: Option<String>,
278}
279
280#[derive(Debug, Clone, Copy, PartialEq, Eq)]
281pub enum TunerKind {
282    Unknown,
283    E4000,
284    Fc0012,
285    Fc0013,
286    Fc2580,
287    R820T,
288    R828D,
289}
290
291impl TunerKind {
292    pub fn is_supported(self) -> bool {
293        matches!(self, Self::R820T | Self::R828D)
294    }
295}
296
297#[derive(Debug, Clone, Copy, PartialEq, Eq)]
298pub enum GainMode {
299    Auto,
300    ManualTenthsDb(i32),
301}
302
303#[derive(Debug, Clone, Copy, PartialEq)]
304pub struct IqSample {
305    pub i: f32,
306    pub q: f32,
307}
308
309pub struct RtlSdr {
310    usb: RtlUsb,
311    vendor_id: u16,
312    product_id: u16,
313    manufacturer: Option<String>,
314    product: Option<String>,
315    tuner: TunerState,
316    rtl_xtal_hz: u32,
317    sample_rate_hz: u32,
318    center_freq_hz: Option<u32>,
319    bandwidth_hz: Option<u32>,
320    freq_correction_ppm: i32,
321}
322
323enum TunerState {
324    Unknown,
325    Unsupported(TunerKind),
326    R82xx(R82xx),
327}
328
329impl RtlSdr {
330    pub async fn open_first() -> Result<Self> {
331        #[cfg(not(target_family = "wasm"))]
332        {
333            let infos = cross_usb::get_device_list(device_filters()).await?;
334            for info in infos {
335                let vendor_id = info.vendor_id().await;
336                let product_id = info.product_id().await;
337                if known_device_name(vendor_id, product_id).is_some() {
338                    return Self::open(info).await;
339                }
340            }
341            Err(Error::DeviceNotFound)
342        }
343
344        #[cfg(target_family = "wasm")]
345        {
346            let info = cross_usb::get_device(device_filters()).await?;
347            Self::open(info).await
348        }
349    }
350
351    #[cfg(not(target_family = "wasm"))]
352    pub async fn list_devices() -> Result<Vec<DeviceDescription>> {
353        let infos = cross_usb::get_device_list(device_filters()).await?;
354        let mut devices = Vec::new();
355
356        for info in infos {
357            let vendor_id = info.vendor_id().await;
358            let product_id = info.product_id().await;
359            let name = known_device_name(vendor_id, product_id);
360            if name.is_none() {
361                continue;
362            }
363            devices.push(DeviceDescription {
364                vendor_id,
365                product_id,
366                name,
367                manufacturer: info.manufacturer_string().await,
368                product: info.product_string().await,
369            });
370        }
371
372        Ok(devices)
373    }
374
375    pub async fn open(info: cross_usb::DeviceInfo) -> Result<Self> {
376        let vendor_id = info.vendor_id().await;
377        let product_id = info.product_id().await;
378        let manufacturer = info.manufacturer_string().await;
379        let product = info.product_string().await;
380        let device = info.open().await?;
381        let interface = device.detach_and_open_interface(0).await?;
382
383        let mut sdr = Self {
384            usb: RtlUsb {
385                _device: device,
386                interface,
387            },
388            vendor_id,
389            product_id,
390            manufacturer,
391            product,
392            tuner: TunerState::Unknown,
393            rtl_xtal_hz: DEF_RTL_XTAL_FREQ,
394            sample_rate_hz: 0,
395            center_freq_hz: None,
396            bandwidth_hz: None,
397            freq_correction_ppm: 0,
398        };
399
400        sdr.usb
401            .write_reg(USBB, USB_SYSCTL, 0x09, 1)
402            .await
403            .context("initial USB_SYSCTL write")?;
404        sdr.init_baseband()
405            .await
406            .context("RTL2832 baseband initialization")?;
407        sdr.probe_tuner().await.context("tuner probe")?;
408        sdr.set_sample_rate(DEFAULT_SAMPLE_RATE)
409            .await
410            .context("default sample-rate setup")?;
411        sdr.reset_buffer().await.context("USB FIFO reset")?;
412
413        Ok(sdr)
414    }
415
416    pub fn vendor_id(&self) -> u16 {
417        self.vendor_id
418    }
419
420    pub fn product_id(&self) -> u16 {
421        self.product_id
422    }
423
424    pub fn known_name(&self) -> Option<&'static str> {
425        known_device_name(self.vendor_id, self.product_id)
426    }
427
428    pub fn manufacturer(&self) -> Option<&str> {
429        self.manufacturer.as_deref()
430    }
431
432    pub fn product(&self) -> Option<&str> {
433        self.product.as_deref()
434    }
435
436    pub fn tuner_kind(&self) -> TunerKind {
437        match &self.tuner {
438            TunerState::Unknown => TunerKind::Unknown,
439            TunerState::Unsupported(kind) => *kind,
440            TunerState::R82xx(tuner) => match tuner.kind() {
441                R82xxKind::R820T => TunerKind::R820T,
442                R82xxKind::R828D => TunerKind::R828D,
443            },
444        }
445    }
446
447    pub fn sample_rate(&self) -> u32 {
448        self.sample_rate_hz
449    }
450
451    pub fn center_frequency(&self) -> Option<u32> {
452        self.center_freq_hz
453    }
454
455    pub fn frequency_correction(&self) -> i32 {
456        self.freq_correction_ppm
457    }
458
459    pub async fn set_sample_rate(&mut self, sample_rate_hz: u32) -> Result<u32> {
460        if sample_rate_hz <= 225_000
461            || sample_rate_hz > 3_200_000
462            || (sample_rate_hz > 300_000 && sample_rate_hz <= 900_000)
463        {
464            return Err(Error::InvalidSampleRate(sample_rate_hz));
465        }
466
467        let numerator = (self.rtl_xtal_hz as u64)
468            .checked_shl(22)
469            .ok_or(Error::ArithmeticOverflow)?;
470        let mut ratio = numerator / sample_rate_hz as u64;
471        ratio &= 0x0fff_fffc;
472        if ratio == 0 {
473            return Err(Error::InvalidSampleRate(sample_rate_hz));
474        }
475
476        let real_ratio = ratio | ((ratio & 0x0800_0000) << 1);
477        let real_rate = (numerator / real_ratio) as u32;
478
479        let bandwidth_hz = self.bandwidth_hz.unwrap_or(real_rate);
480        let new_if = if matches!(self.tuner, TunerState::R82xx(_)) {
481            self.set_i2c_repeater(true).await?;
482            let result = match &mut self.tuner {
483                TunerState::R82xx(tuner) => {
484                    tuner
485                        .set_bandwidth(&self.usb, bandwidth_hz, real_rate)
486                        .await
487                }
488                _ => unreachable!(),
489            };
490            let repeater_result = self.set_i2c_repeater(false).await;
491            let if_hz = result?;
492            repeater_result?;
493            Some(if_hz)
494        } else {
495            None
496        };
497        if let Some(if_hz) = new_if {
498            self.set_if_freq(if_hz).await?;
499        }
500
501        self.usb
502            .demod_write_reg(1, 0x9f, ((ratio >> 16) & 0xffff) as u16, 2)
503            .await?;
504        self.usb
505            .demod_write_reg(1, 0xa1, (ratio & 0xffff) as u16, 2)
506            .await?;
507        self.set_sample_freq_correction(self.freq_correction_ppm)
508            .await?;
509        self.reset_demod().await?;
510
511        self.sample_rate_hz = real_rate;
512        if self.center_freq_hz.is_some() && new_if.is_some() {
513            self.retune().await?;
514        }
515
516        Ok(real_rate)
517    }
518
519    pub async fn set_center_frequency(&mut self, frequency_hz: u32) -> Result<()> {
520        if frequency_hz == 0 {
521            return Err(Error::InvalidFrequency(frequency_hz));
522        }
523
524        self.set_i2c_repeater(true).await?;
525        let result = match &mut self.tuner {
526            TunerState::R82xx(tuner) => tuner.set_freq(&self.usb, frequency_hz).await,
527            TunerState::Unsupported(kind) => Err(Error::UnsupportedTuner(*kind)),
528            TunerState::Unknown => Err(Error::TunerNotFound),
529        };
530        let repeater_result = self.set_i2c_repeater(false).await;
531
532        result?;
533        repeater_result?;
534
535        self.center_freq_hz = Some(frequency_hz);
536        Ok(())
537    }
538
539    pub async fn set_tuner_gain(&mut self, gain: GainMode) -> Result<()> {
540        let (manual, gain_tenths_db) = match gain {
541            GainMode::Auto => (false, 0),
542            GainMode::ManualTenthsDb(gain) => {
543                if !(-100..=500).contains(&gain) {
544                    return Err(Error::InvalidGain(gain));
545                }
546                (true, gain)
547            }
548        };
549
550        self.set_i2c_repeater(true).await?;
551        let result = match &mut self.tuner {
552            TunerState::R82xx(tuner) => tuner.set_gain(&self.usb, manual, gain_tenths_db).await,
553            TunerState::Unsupported(kind) => Err(Error::UnsupportedTuner(*kind)),
554            TunerState::Unknown => Err(Error::TunerNotFound),
555        };
556        let repeater_result = self.set_i2c_repeater(false).await;
557
558        result?;
559        repeater_result?;
560
561        Ok(())
562    }
563
564    pub async fn set_bandwidth(&mut self, bandwidth_hz: Option<u32>) -> Result<()> {
565        self.bandwidth_hz = bandwidth_hz;
566        let bandwidth = bandwidth_hz.unwrap_or(self.sample_rate_hz);
567        self.set_i2c_repeater(true).await?;
568        let result = match &mut self.tuner {
569            TunerState::R82xx(tuner) => {
570                tuner
571                    .set_bandwidth(&self.usb, bandwidth, self.sample_rate_hz)
572                    .await
573            }
574            TunerState::Unsupported(kind) => Err(Error::UnsupportedTuner(*kind)),
575            TunerState::Unknown => Err(Error::TunerNotFound),
576        };
577        let repeater_result = self.set_i2c_repeater(false).await;
578        let new_if = Some(result?);
579        repeater_result?;
580
581        if let Some(if_hz) = new_if {
582            self.set_if_freq(if_hz).await?;
583            if self.center_freq_hz.is_some() {
584                self.retune().await?;
585            }
586        }
587
588        Ok(())
589    }
590
591    pub async fn set_frequency_correction(&mut self, ppm: i32) -> Result<()> {
592        self.freq_correction_ppm = ppm;
593        self.set_sample_freq_correction(ppm).await?;
594        if self.center_freq_hz.is_some() {
595            self.retune().await?;
596        }
597        Ok(())
598    }
599
600    pub async fn set_agc_mode(&self, enabled: bool) -> Result<()> {
601        self.usb
602            .demod_write_reg(0, 0x19, if enabled { 0x25 } else { 0x05 }, 1)
603            .await
604    }
605
606    pub async fn set_test_mode(&self, enabled: bool) -> Result<()> {
607        self.usb
608            .demod_write_reg(0, 0x19, if enabled { 0x03 } else { 0x05 }, 1)
609            .await
610    }
611
612    pub async fn reset_buffer(&self) -> Result<()> {
613        self.usb.write_reg(USBB, USB_EPA_CTL, 0x1002, 2).await?;
614        self.usb.write_reg(USBB, USB_EPA_CTL, 0x0000, 2).await
615    }
616
617    pub async fn read_bytes(&self, len: usize) -> Result<Vec<u8>> {
618        let len = if len == 0 { DEFAULT_READ_LENGTH } else { len };
619        self.usb
620            .interface
621            .bulk_in(DEFAULT_BULK_ENDPOINT, len)
622            .await
623            .map_err(Error::from)
624    }
625
626    pub async fn read_iq_samples(&self, sample_count: usize) -> Result<Vec<IqSample>> {
627        let bytes = self.read_bytes(sample_count.saturating_mul(2)).await?;
628        Ok(bytes_to_iq_samples(&bytes))
629    }
630
631    async fn init_baseband(&mut self) -> Result<()> {
632        self.usb.write_reg(USBB, USB_SYSCTL, 0x09, 1).await?;
633        self.usb.write_reg(USBB, USB_EPA_MAXPKT, 0x0002, 2).await?;
634        self.usb.write_reg(USBB, USB_EPA_CTL, 0x1002, 2).await?;
635
636        self.usb.write_reg(SYSB, DEMOD_CTL_1, 0x22, 1).await?;
637        self.usb.write_reg(SYSB, DEMOD_CTL, 0xe8, 1).await?;
638        self.reset_demod().await?;
639
640        self.usb.demod_write_reg(1, 0x15, 0x00, 1).await?;
641        self.usb.demod_write_reg(1, 0x16, 0x0000, 2).await?;
642        for offset in 0..6 {
643            self.usb.demod_write_reg(1, 0x16 + offset, 0x00, 1).await?;
644        }
645
646        self.set_fir().await?;
647        self.usb.demod_write_reg(0, 0x19, 0x05, 1).await?;
648        self.usb.demod_write_reg(1, 0x93, 0xf0, 1).await?;
649        self.usb.demod_write_reg(1, 0x94, 0x0f, 1).await?;
650        self.usb.demod_write_reg(1, 0x11, 0x00, 1).await?;
651        self.usb.demod_write_reg(1, 0x04, 0x00, 1).await?;
652        self.usb.demod_write_reg(0, 0x61, 0x60, 1).await?;
653        self.usb.demod_write_reg(0, 0x06, 0x80, 1).await?;
654        self.usb.demod_write_reg(1, 0xb1, 0x1b, 1).await?;
655        self.usb.demod_write_reg(0, 0x0d, 0x83, 1).await
656    }
657
658    async fn probe_tuner(&mut self) -> Result<()> {
659        self.set_i2c_repeater(true).await?;
660        let result = self.probe_tuner_inner().await;
661        let repeater_result = self.set_i2c_repeater(false).await;
662
663        result?;
664        repeater_result?;
665        Ok(())
666    }
667
668    async fn probe_tuner_inner(&mut self) -> Result<()> {
669        if self.try_i2c_read_reg(E4K_I2C_ADDR, E4K_CHECK_ADDR).await == Some(E4K_CHECK_VAL) {
670            self.tuner = TunerState::Unsupported(TunerKind::E4000);
671            return Ok(());
672        }
673        if self
674            .try_i2c_read_reg(FC0013_I2C_ADDR, FC0013_CHECK_ADDR)
675            .await
676            == Some(FC0013_CHECK_VAL)
677        {
678            self.tuner = TunerState::Unsupported(TunerKind::Fc0013);
679            return Ok(());
680        }
681        if self
682            .try_i2c_read_reg(R820T_I2C_ADDR, R82XX_CHECK_ADDR)
683            .await
684            == Some(R82XX_CHECK_VAL)
685        {
686            self.configure_r82xx(R82xxKind::R820T).await?;
687            return Ok(());
688        }
689        if self
690            .try_i2c_read_reg(R828D_I2C_ADDR, R82XX_CHECK_ADDR)
691            .await
692            == Some(R82XX_CHECK_VAL)
693        {
694            self.configure_r82xx(R82xxKind::R828D).await?;
695            return Ok(());
696        }
697
698        self.set_gpio_output(4).await?;
699        self.set_gpio_bit(4, true).await?;
700        self.set_gpio_bit(4, false).await?;
701
702        if self
703            .try_i2c_read_reg(FC2580_I2C_ADDR, FC2580_CHECK_ADDR)
704            .await
705            .is_some_and(|reg| (reg & 0x7f) == FC2580_CHECK_VAL)
706        {
707            self.tuner = TunerState::Unsupported(TunerKind::Fc2580);
708            return Ok(());
709        }
710        if self
711            .try_i2c_read_reg(FC0012_I2C_ADDR, FC0012_CHECK_ADDR)
712            .await
713            == Some(FC0012_CHECK_VAL)
714        {
715            self.set_gpio_output(6).await?;
716            self.tuner = TunerState::Unsupported(TunerKind::Fc0012);
717            return Ok(());
718        }
719
720        self.tuner = TunerState::Unknown;
721        Ok(())
722    }
723
724    async fn configure_r82xx(&mut self, kind: R82xxKind) -> Result<()> {
725        self.usb.demod_write_reg(1, 0xb1, 0x1a, 1).await?;
726        self.usb.demod_write_reg(0, 0x08, 0x4d, 1).await?;
727        self.set_if_freq(R82XX_IF_FREQ).await?;
728        self.usb.demod_write_reg(1, 0x15, 0x01, 1).await?;
729
730        let tuner_xtal = match kind {
731            R82xxKind::R820T => self.rtl_xtal_hz,
732            R82xxKind::R828D if self.is_blog_v4() => self.rtl_xtal_hz,
733            R82xxKind::R828D => R828D_XTAL_FREQ,
734        };
735
736        let mut tuner = R82xx::new(kind, tuner_xtal, self.is_blog_v4());
737        tuner.init(&self.usb).await?;
738        self.tuner = TunerState::R82xx(tuner);
739        Ok(())
740    }
741
742    async fn retune(&mut self) -> Result<()> {
743        if let Some(frequency) = self.center_freq_hz {
744            self.set_center_frequency(frequency).await?;
745        }
746        Ok(())
747    }
748
749    async fn set_if_freq(&self, frequency_hz: u32) -> Result<()> {
750        let ratio = ((frequency_hz as i64) << 22) / self.rtl_xtal_hz as i64;
751        let if_freq = -ratio;
752        self.usb
753            .demod_write_reg(1, 0x19, ((if_freq >> 16) & 0x3f) as u16, 1)
754            .await?;
755        self.usb
756            .demod_write_reg(1, 0x1a, ((if_freq >> 8) & 0xff) as u16, 1)
757            .await?;
758        self.usb
759            .demod_write_reg(1, 0x1b, (if_freq & 0xff) as u16, 1)
760            .await
761    }
762
763    async fn set_sample_freq_correction(&self, ppm: i32) -> Result<()> {
764        let offset = (ppm as i64)
765            .checked_mul(-1)
766            .and_then(|v| v.checked_mul(1 << 24))
767            .ok_or(Error::ArithmeticOverflow)?
768            / 1_000_000;
769        self.usb
770            .demod_write_reg(1, 0x3f, (offset & 0xff) as u16, 1)
771            .await?;
772        self.usb
773            .demod_write_reg(1, 0x3e, ((offset >> 8) & 0x3f) as u16, 1)
774            .await
775    }
776
777    async fn reset_demod(&self) -> Result<()> {
778        self.usb.demod_write_reg(1, 0x01, 0x14, 1).await?;
779        self.usb.demod_write_reg(1, 0x01, 0x10, 1).await
780    }
781
782    async fn set_i2c_repeater(&self, enabled: bool) -> Result<()> {
783        self.usb
784            .demod_write_reg(1, 0x01, if enabled { 0x18 } else { 0x10 }, 1)
785            .await
786    }
787
788    async fn set_fir(&self) -> Result<()> {
789        let mut fir = [0u8; 20];
790        for (i, value) in FIR_DEFAULT.iter().take(8).enumerate() {
791            fir[i] = *value as i8 as u8;
792        }
793        for i in (0..8).step_by(2) {
794            let val0 = FIR_DEFAULT[8 + i];
795            let val1 = FIR_DEFAULT[8 + i + 1];
796            let out = 8 + i * 3 / 2;
797            fir[out] = (val0 >> 4) as u8;
798            fir[out + 1] = ((val0 << 4) as u8) | (((val1 >> 8) as u8) & 0x0f);
799            fir[out + 2] = val1 as u8;
800        }
801
802        for (offset, value) in fir.into_iter().enumerate() {
803            self.usb
804                .demod_write_reg(1, 0x1c + offset as u16, value as u16, 1)
805                .await?;
806        }
807
808        Ok(())
809    }
810
811    async fn try_i2c_read_reg(&self, i2c_addr: u8, reg: u8) -> Option<u8> {
812        self.usb.i2c_read_reg(i2c_addr, reg).await.ok()
813    }
814
815    async fn set_gpio_output(&self, gpio: u8) -> Result<()> {
816        self.usb.set_gpio_output(gpio).await
817    }
818
819    pub(crate) async fn set_gpio_bit(&self, gpio: u8, enabled: bool) -> Result<()> {
820        self.usb.set_gpio_bit(gpio, enabled).await
821    }
822
823    fn is_blog_v4(&self) -> bool {
824        self.manufacturer.as_deref() == Some("RTLSDRBlog")
825            && self.product.as_deref() == Some("Blog V4")
826    }
827}
828
829pub fn bytes_to_iq_samples(bytes: &[u8]) -> Vec<IqSample> {
830    bytes
831        .chunks_exact(2)
832        .map(|pair| IqSample {
833            i: (pair[0] as f32 - 127.5) / 127.5,
834            q: (pair[1] as f32 - 127.5) / 127.5,
835        })
836        .collect()
837}
838
839pub(crate) struct RtlUsb {
840    _device: cross_usb::Device,
841    interface: cross_usb::Interface,
842}
843
844impl RtlUsb {
845    pub(crate) async fn set_gpio_output(&self, gpio: u8) -> Result<()> {
846        let bit = 1u16 << gpio;
847        let direction = self.read_reg(SYSB, GPD, 1).await?;
848        self.write_reg(SYSB, GPD, direction & !bit, 1).await?;
849        let output_enable = self.read_reg(SYSB, GPOE, 1).await?;
850        self.write_reg(SYSB, GPOE, output_enable | bit, 1).await
851    }
852
853    pub(crate) async fn set_gpio_bit(&self, gpio: u8, enabled: bool) -> Result<()> {
854        let bit = 1u16 << gpio;
855        let value = self.read_reg(SYSB, GPO, 1).await?;
856        let value = if enabled { value | bit } else { value & !bit };
857        self.write_reg(SYSB, GPO, value, 1).await
858    }
859    pub(crate) async fn read_reg(&self, block: u8, addr: u16, len: u16) -> Result<u16> {
860        let data = self.read_array(block, addr, len).await?;
861        Ok(match data.as_slice() {
862            [lo] => *lo as u16,
863            [lo, hi, ..] => ((*hi as u16) << 8) | *lo as u16,
864            _ => 0,
865        })
866    }
867
868    pub(crate) async fn write_reg(
869        &self,
870        block: u8,
871        addr: u16,
872        value: u16,
873        len: usize,
874    ) -> Result<()> {
875        let data = reg_value_bytes(value, len)?;
876        self.write_array(block, addr, &data).await
877    }
878
879    pub(crate) async fn read_array(&self, block: u8, addr: u16, len: u16) -> Result<Vec<u8>> {
880        self.interface
881            .control_in(ControlIn {
882                control_type: ControlType::Vendor,
883                recipient: Recipient::Device,
884                request: 0,
885                value: addr,
886                index: (block as u16) << 8,
887                length: len,
888            })
889            .await
890            .map_err(Error::from)
891            .map_err(|err| err.control("control_in", addr, (block as u16) << 8))
892    }
893
894    pub(crate) async fn write_array(&self, block: u8, addr: u16, data: &[u8]) -> Result<()> {
895        if data.len() > u16::MAX as usize {
896            return Err(Error::InvalidTransferLength(data.len()));
897        }
898
899        let actual = self
900            .interface
901            .control_out(ControlOut {
902                control_type: ControlType::Vendor,
903                recipient: Recipient::Device,
904                request: 0,
905                value: addr,
906                index: ((block as u16) << 8) | 0x10,
907                data,
908            })
909            .await
910            .map_err(Error::from)
911            .map_err(|err| err.control("control_out", addr, ((block as u16) << 8) | 0x10))?;
912
913        if actual == data.len() {
914            Ok(())
915        } else {
916            Err(Error::ShortTransfer {
917                expected: data.len(),
918                actual,
919            })
920        }
921    }
922
923    pub(crate) async fn demod_write_reg(
924        &self,
925        page: u8,
926        addr: u16,
927        value: u16,
928        len: usize,
929    ) -> Result<()> {
930        let data = reg_value_bytes(value, len)?;
931        let actual = self
932            .interface
933            .control_out(ControlOut {
934                control_type: ControlType::Vendor,
935                recipient: Recipient::Device,
936                request: 0,
937                value: (addr << 8) | 0x20,
938                index: 0x10 | page as u16,
939                data: &data,
940            })
941            .await
942            .map_err(Error::from)
943            .map_err(|err| {
944                err.control("demod_control_out", (addr << 8) | 0x20, 0x10 | page as u16)
945            })?;
946
947        if actual != data.len() {
948            return Err(Error::ShortTransfer {
949                expected: data.len(),
950                actual,
951            });
952        }
953
954        let _ = self.demod_read_reg(0x0a, 0x01, 1).await?;
955        Ok(())
956    }
957
958    pub(crate) async fn demod_read_reg(&self, page: u8, addr: u16, len: u16) -> Result<u16> {
959        let data = self
960            .interface
961            .control_in(ControlIn {
962                control_type: ControlType::Vendor,
963                recipient: Recipient::Device,
964                request: 0,
965                value: (addr << 8) | 0x20,
966                index: page as u16,
967                length: len,
968            })
969            .await
970            .map_err(Error::from)
971            .map_err(|err| err.control("demod_control_in", (addr << 8) | 0x20, page as u16))?;
972
973        Ok(match data.as_slice() {
974            [lo] => *lo as u16,
975            [lo, hi, ..] => ((*hi as u16) << 8) | *lo as u16,
976            _ => 0,
977        })
978    }
979
980    pub(crate) async fn i2c_write(&self, i2c_addr: u8, data: &[u8]) -> Result<()> {
981        self.write_array(IICB, i2c_addr as u16, data).await
982    }
983
984    pub(crate) async fn i2c_read(&self, i2c_addr: u8, len: u16) -> Result<Vec<u8>> {
985        self.read_array(IICB, i2c_addr as u16, len).await
986    }
987
988    pub(crate) async fn i2c_read_reg(&self, i2c_addr: u8, reg: u8) -> Result<u8> {
989        self.i2c_write(i2c_addr, &[reg]).await?;
990        let data = self.i2c_read(i2c_addr, 1).await?;
991        data.first().copied().ok_or(Error::ShortTransfer {
992            expected: 1,
993            actual: 0,
994        })
995    }
996}
997
998fn reg_value_bytes(value: u16, len: usize) -> Result<Vec<u8>> {
999    match len {
1000        1 => Ok(vec![(value & 0xff) as u8]),
1001        2 => Ok(vec![(value >> 8) as u8, (value & 0xff) as u8]),
1002        _ => Err(Error::InvalidTransferLength(len)),
1003    }
1004}
1005
1006fn device_filters() -> Vec<cross_usb::DeviceFilter> {
1007    KNOWN_DEVICES
1008        .iter()
1009        .map(|device| {
1010            cross_usb::DeviceFilter::new(
1011                Some(device.vendor_id),
1012                Some(device.product_id),
1013                None,
1014                None,
1015                None,
1016            )
1017        })
1018        .collect()
1019}
1020
1021fn known_device_name(vendor_id: u16, product_id: u16) -> Option<&'static str> {
1022    KNOWN_DEVICES
1023        .iter()
1024        .find(|device| device.vendor_id == vendor_id && device.product_id == product_id)
1025        .map(|device| device.name)
1026}