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}