Skip to main content

seify/
device.rs

1#![allow(dead_code)]
2#![allow(unused_variables)]
3use serde::{Deserialize, Serialize};
4use std::any::Any;
5use std::sync::Arc;
6
7use crate::Args;
8use crate::Capability;
9use crate::Direction;
10use crate::Driver;
11use crate::Error;
12use crate::Range;
13use crate::Registry;
14use crate::RxStreamer;
15use crate::TxStreamer;
16use crate::TypedDeviceBackend;
17
18/// Type-erased RX streamer.
19pub type DynRxStreamer = Box<dyn RxStreamer>;
20
21/// Type-erased TX streamer.
22pub type DynTxStreamer = Box<dyn TxStreamer>;
23
24/// Object-safe RX streaming capability for runtime-dispatched devices.
25pub trait ErasedRxDevice {
26    /// Create a type-erased RX streamer.
27    fn rx_streamer(&self, channels: &[usize], args: Args) -> Result<DynRxStreamer, Error>;
28}
29
30impl<T> ErasedRxDevice for T
31where
32    T: RxDevice,
33    T::RxStreamer: 'static,
34{
35    fn rx_streamer(&self, channels: &[usize], args: Args) -> Result<DynRxStreamer, Error> {
36        Ok(Box::new(RxDevice::rx_streamer(self, channels, args)?))
37    }
38}
39
40/// Object-safe TX streaming capability for runtime-dispatched devices.
41pub trait ErasedTxDevice {
42    /// Create a type-erased TX streamer.
43    fn tx_streamer(&self, channels: &[usize], args: Args) -> Result<DynTxStreamer, Error>;
44}
45
46impl<T> ErasedTxDevice for T
47where
48    T: TxDevice,
49    T::TxStreamer: 'static,
50{
51    fn tx_streamer(&self, channels: &[usize], args: Args) -> Result<DynTxStreamer, Error> {
52        Ok(Box::new(TxDevice::tx_streamer(self, channels, args)?))
53    }
54}
55
56/// Runtime-dispatched device backend.
57///
58/// The erased backend only exposes device metadata and optional views into
59/// capability traits. Individual controls live on the smaller capability traits
60/// instead of one mandatory universal device interface.
61pub trait DynDeviceBackend: DeviceInfo + Send + Sync {
62    /// Return a structured snapshot of the device's runtime capabilities.
63    fn capabilities(&self) -> Result<DeviceCapabilities, Error> {
64        DeviceCapabilities::from_dyn(self)
65    }
66
67    /// Return channel metadata capability, if the backend exposes it.
68    fn channel_info(&self) -> Option<&dyn ChannelInfo> {
69        None
70    }
71
72    /// Return RX streaming capability, if the backend exposes it.
73    fn rx_device(&self) -> Option<&dyn ErasedRxDevice> {
74        None
75    }
76
77    /// Return TX streaming capability, if the backend exposes it.
78    fn tx_device(&self) -> Option<&dyn ErasedTxDevice> {
79        None
80    }
81
82    /// Return antenna control capability, if the backend exposes it.
83    fn antenna_control(&self) -> Option<&dyn AntennaControl> {
84        None
85    }
86
87    /// Return automatic gain control capability, if the backend exposes it.
88    fn agc_control(&self) -> Option<&dyn AgcControl> {
89        None
90    }
91
92    /// Return gain control capability, if the backend exposes it.
93    fn gain_control(&self) -> Option<&dyn GainControl> {
94        None
95    }
96
97    /// Return frequency control capability, if the backend exposes it.
98    fn frequency_control(&self) -> Option<&dyn FrequencyControl> {
99        None
100    }
101
102    /// Return sample-rate control capability, if the backend exposes it.
103    fn sample_rate_control(&self) -> Option<&dyn SampleRateControl> {
104        None
105    }
106
107    /// Return bandwidth control capability, if the backend exposes it.
108    fn bandwidth_control(&self) -> Option<&dyn BandwidthControl> {
109        None
110    }
111
112    /// Return DC offset control capability, if the backend exposes it.
113    fn dc_offset_control(&self) -> Option<&dyn DcOffsetControl> {
114        None
115    }
116}
117
118/// Runtime-dispatched opened device.
119///
120/// This is used to control a device when the concrete driver implementation is
121/// not known at compile time.
122#[derive(Clone)]
123pub struct DynDevice {
124    inner: Arc<dyn DynDeviceBackend>,
125}
126
127/// Structured runtime capabilities for a device.
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct DeviceCapabilities {
130    /// RX channels exposed by this device.
131    pub rx_channels: Vec<ChannelCapabilities>,
132    /// TX channels exposed by this device.
133    pub tx_channels: Vec<ChannelCapabilities>,
134}
135
136impl DeviceCapabilities {
137    /// Build a capability snapshot from a runtime-dispatched backend.
138    pub fn from_dyn<D: DynDeviceBackend + ?Sized>(dev: &D) -> Result<Self, Error> {
139        Ok(Self {
140            rx_channels: channel_capabilities(dev, Direction::Rx)?,
141            tx_channels: channel_capabilities(dev, Direction::Tx)?,
142        })
143    }
144}
145
146/// Structured runtime capabilities for one channel.
147#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
148pub struct ChannelCapabilities {
149    /// Channel index within its direction.
150    pub channel: usize,
151    /// Full-duplex support for this channel, if the backend exposes it.
152    pub full_duplex: Option<bool>,
153    /// Optional controls exposed by this channel.
154    pub controls: ChannelControls,
155}
156
157/// Optional controls exposed by one channel.
158#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
159pub struct ChannelControls {
160    /// Available antenna ports.
161    pub antennas: Option<Vec<String>>,
162    /// Automatic gain control support.
163    pub agc: bool,
164    /// Named gain elements.
165    pub gain_elements: Option<Vec<String>>,
166    /// Overall gain range.
167    pub gain_range: Option<Range>,
168    /// Named frequency components.
169    pub frequency_components: Option<Vec<String>>,
170    /// Overall frequency range.
171    pub frequency_range: Option<Range>,
172    /// Baseband sample-rate range.
173    pub sample_rate_range: Option<Range>,
174    /// Hardware bandwidth range.
175    pub bandwidth_range: Option<Range>,
176    /// Automatic DC offset correction support.
177    pub dc_offset: bool,
178}
179
180fn channel_capabilities<D>(dev: &D, direction: Direction) -> Result<Vec<ChannelCapabilities>, Error>
181where
182    D: DynDeviceBackend + ?Sized,
183{
184    let Some(channel_info) = dev.channel_info() else {
185        return Ok(Vec::new());
186    };
187    let channels = match channel_info.num_channels(direction) {
188        Ok(channels) => channels,
189        Err(e) if e.is_unsupported() => 0,
190        Err(e) => return Err(e),
191    };
192
193    (0..channels)
194        .map(|channel| {
195            Ok(ChannelCapabilities {
196                channel,
197                full_duplex: optional_capability(channel_info.full_duplex(direction, channel))?,
198                controls: ChannelControls {
199                    antennas: optional_erased_capability(dev.antenna_control(), |cap| {
200                        cap.antennas(direction, channel)
201                    })?,
202                    agc: erased_capability_available(dev.agc_control(), |cap| {
203                        cap.agc_available(direction, channel)
204                    })?,
205                    gain_elements: optional_erased_capability(dev.gain_control(), |cap| {
206                        cap.gain_elements(direction, channel)
207                    })?,
208                    gain_range: optional_erased_capability(dev.gain_control(), |cap| {
209                        cap.gain_range(direction, channel)
210                    })?,
211                    frequency_components: optional_erased_capability(
212                        dev.frequency_control(),
213                        |cap| cap.frequency_components(direction, channel),
214                    )?,
215                    frequency_range: optional_erased_capability(dev.frequency_control(), |cap| {
216                        cap.frequency_range(direction, channel)
217                    })?,
218                    sample_rate_range: optional_erased_capability(
219                        dev.sample_rate_control(),
220                        |cap| cap.get_sample_rate_range(direction, channel),
221                    )?,
222                    bandwidth_range: optional_erased_capability(dev.bandwidth_control(), |cap| {
223                        cap.get_bandwidth_range(direction, channel)
224                    })?,
225                    dc_offset: erased_capability_available(dev.dc_offset_control(), |cap| {
226                        cap.dc_offset_available(direction, channel)
227                    })?,
228                },
229            })
230        })
231        .collect()
232}
233
234fn optional_capability<T>(result: Result<T, Error>) -> Result<Option<T>, Error> {
235    match result {
236        Ok(value) => Ok(Some(value)),
237        Err(e) if e.is_unsupported() => Ok(None),
238        Err(e) => Err(e),
239    }
240}
241
242fn optional_erased_capability<C: ?Sized, T>(
243    cap: Option<&C>,
244    f: impl FnOnce(&C) -> Result<T, Error>,
245) -> Result<Option<T>, Error> {
246    match cap {
247        Some(cap) => optional_capability(f(cap)),
248        None => Ok(None),
249    }
250}
251
252fn erased_capability_available<C: ?Sized>(
253    cap: Option<&C>,
254    f: impl FnOnce(&C) -> Result<bool, Error>,
255) -> Result<bool, Error> {
256    match cap {
257        Some(cap) => match f(cap) {
258            Ok(available) => Ok(available),
259            Err(e) if e.is_unsupported() => Ok(false),
260            Err(e) => Err(e),
261        },
262        None => Ok(false),
263    }
264}
265
266/// Basic device metadata.
267pub trait DeviceInfo {
268    /// Cast to [`Any`] for downcasting.
269    fn as_any(&self) -> &dyn Any;
270    /// Cast to [`Any`] for mutable downcasting.
271    fn as_any_mut(&mut self) -> &mut dyn Any;
272    /// SDR [driver](Driver).
273    fn driver(&self) -> Driver;
274    /// Identifier for the device, e.g. its serial.
275    fn id(&self) -> Result<String, Error>;
276    /// Device info that can be displayed to the user.
277    fn info(&self) -> Result<Args, Error>;
278}
279
280/// Basic channel metadata.
281pub trait ChannelInfo {
282    /// Number of supported channels.
283    fn num_channels(&self, direction: Direction) -> Result<usize, Error>;
284    /// Full-duplex support.
285    fn full_duplex(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
286}
287
288/// RX streaming capability.
289pub trait RxDevice {
290    /// RX streamer implementation.
291    type RxStreamer: RxStreamer;
292
293    /// Create an RX streamer.
294    fn rx_streamer(&self, channels: &[usize], args: Args) -> Result<Self::RxStreamer, Error>;
295}
296
297/// TX streaming capability.
298pub trait TxDevice {
299    /// TX streamer implementation.
300    type TxStreamer: TxStreamer;
301
302    /// Create a TX streamer.
303    fn tx_streamer(&self, channels: &[usize], args: Args) -> Result<Self::TxStreamer, Error>;
304}
305
306/// Antenna control capability.
307pub trait AntennaControl {
308    /// Return available antenna port names.
309    fn antennas(&self, direction: Direction, channel: usize) -> Result<Vec<String>, Error>;
310    /// Return the currently selected antenna port name.
311    fn antenna(&self, direction: Direction, channel: usize) -> Result<String, Error>;
312    /// Select an antenna port by name.
313    fn set_antenna(&self, direction: Direction, channel: usize, name: &str) -> Result<(), Error>;
314}
315
316/// Automatic gain control capability.
317pub trait AgcControl {
318    /// Return whether automatic gain control is available.
319    fn agc_available(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
320    /// Return whether automatic gain control is currently enabled.
321    fn agc_enabled(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
322    /// Enable or disable automatic gain control.
323    fn set_agc_enabled(
324        &self,
325        direction: Direction,
326        channel: usize,
327        enabled: bool,
328    ) -> Result<(), Error>;
329}
330
331/// Gain control capability.
332pub trait GainControl {
333    /// Return named gain elements available for the channel.
334    fn gain_elements(&self, direction: Direction, channel: usize) -> Result<Vec<String>, Error>;
335    /// Set overall channel gain in dB.
336    fn set_gain(&self, direction: Direction, channel: usize, gain: f64) -> Result<(), Error>;
337    /// Return overall channel gain in dB, if available.
338    fn gain(&self, direction: Direction, channel: usize) -> Result<Option<f64>, Error>;
339    /// Return supported overall channel gain range in dB.
340    fn gain_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
341    /// Set a named gain element in dB.
342    fn set_gain_element(
343        &self,
344        direction: Direction,
345        channel: usize,
346        name: &str,
347        gain: f64,
348    ) -> Result<(), Error>;
349    /// Return a named gain element in dB, if available.
350    fn gain_element(
351        &self,
352        direction: Direction,
353        channel: usize,
354        name: &str,
355    ) -> Result<Option<f64>, Error>;
356    /// Return supported range in dB for a named gain element.
357    fn gain_element_range(
358        &self,
359        direction: Direction,
360        channel: usize,
361        name: &str,
362    ) -> Result<Range, Error>;
363}
364
365/// Frequency control capability.
366pub trait FrequencyControl {
367    /// Return supported overall tuning range in Hz.
368    fn frequency_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
369    /// Return current overall channel frequency in Hz.
370    fn frequency(&self, direction: Direction, channel: usize) -> Result<f64, Error>;
371    /// Set overall channel frequency in Hz with optional driver arguments.
372    fn set_frequency(
373        &self,
374        direction: Direction,
375        channel: usize,
376        frequency: f64,
377        args: Args,
378    ) -> Result<(), Error>;
379    /// Return named frequency components for the channel.
380    fn frequency_components(
381        &self,
382        direction: Direction,
383        channel: usize,
384    ) -> Result<Vec<String>, Error>;
385    /// Return supported range in Hz for a named frequency component.
386    fn component_frequency_range(
387        &self,
388        direction: Direction,
389        channel: usize,
390        name: &str,
391    ) -> Result<Range, Error>;
392    /// Return current frequency in Hz for a named frequency component.
393    fn component_frequency(
394        &self,
395        direction: Direction,
396        channel: usize,
397        name: &str,
398    ) -> Result<f64, Error>;
399    /// Set frequency in Hz for a named frequency component.
400    fn set_component_frequency(
401        &self,
402        direction: Direction,
403        channel: usize,
404        name: &str,
405        frequency: f64,
406    ) -> Result<(), Error>;
407}
408
409/// Sample-rate control capability.
410pub trait SampleRateControl {
411    /// Return current sample rate in samples per second.
412    fn sample_rate(&self, direction: Direction, channel: usize) -> Result<f64, Error>;
413    /// Set sample rate in samples per second.
414    fn set_sample_rate(&self, direction: Direction, channel: usize, rate: f64)
415        -> Result<(), Error>;
416    /// Return supported sample-rate range in samples per second.
417    fn get_sample_rate_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
418}
419
420/// Bandwidth control capability.
421pub trait BandwidthControl {
422    /// Return current channel bandwidth in Hz.
423    fn bandwidth(&self, direction: Direction, channel: usize) -> Result<f64, Error>;
424    /// Set channel bandwidth in Hz.
425    fn set_bandwidth(&self, direction: Direction, channel: usize, bw: f64) -> Result<(), Error>;
426    /// Return supported channel bandwidth range in Hz.
427    fn get_bandwidth_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
428}
429
430/// Automatic DC offset correction capability.
431pub trait DcOffsetControl {
432    /// Return whether automatic DC offset correction is available.
433    fn dc_offset_available(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
434    /// Return whether automatic DC offset correction is enabled.
435    fn dc_offset_enabled(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
436    /// Enable or disable automatic DC offset correction.
437    fn set_dc_offset_enabled(
438        &self,
439        direction: Direction,
440        channel: usize,
441        enabled: bool,
442    ) -> Result<(), Error>;
443}
444
445/// RX channel handle.
446pub struct RxChannel<'a, T: ?Sized> {
447    dev: &'a T,
448    channel: usize,
449}
450
451impl<'a, T: ?Sized> RxChannel<'a, T> {
452    fn new(dev: &'a T, channel: usize) -> Self {
453        Self { dev, channel }
454    }
455
456    /// Channel index.
457    pub fn id(&self) -> usize {
458        self.channel
459    }
460
461    /// Channel index.
462    pub fn index(&self) -> usize {
463        self.channel
464    }
465}
466
467/// TX channel handle.
468pub struct TxChannel<'a, T: ?Sized> {
469    dev: &'a T,
470    channel: usize,
471}
472
473impl<'a, T: ?Sized> TxChannel<'a, T> {
474    fn new(dev: &'a T, channel: usize) -> Self {
475        Self { dev, channel }
476    }
477
478    /// Channel index.
479    pub fn id(&self) -> usize {
480        self.channel
481    }
482
483    /// Channel index.
484    pub fn index(&self) -> usize {
485        self.channel
486    }
487}
488
489/// Antenna control handle for one channel.
490pub struct Antenna<'a, T: AntennaControl + ?Sized> {
491    dev: &'a T,
492    direction: Direction,
493    channel: usize,
494}
495
496impl<'a, T> Antenna<'a, T>
497where
498    T: AntennaControl + ?Sized,
499{
500    fn new(dev: &'a T, direction: Direction, channel: usize) -> Self {
501        Self {
502            dev,
503            direction,
504            channel,
505        }
506    }
507
508    /// Selectable antenna ports.
509    pub fn ports(&self) -> Result<Vec<String>, Error> {
510        self.dev.antennas(self.direction, self.channel)
511    }
512
513    /// Currently selected antenna.
514    pub fn selected(&self) -> Result<String, Error> {
515        self.dev.antenna(self.direction, self.channel)
516    }
517
518    /// Select an antenna port.
519    pub fn select(&self, name: &str) -> Result<(), Error> {
520        self.dev.set_antenna(self.direction, self.channel, name)
521    }
522}
523
524/// Automatic gain control handle for one channel.
525pub struct Agc<'a, T: AgcControl + ?Sized> {
526    dev: &'a T,
527    direction: Direction,
528    channel: usize,
529}
530
531impl<'a, T> Agc<'a, T>
532where
533    T: AgcControl + ?Sized,
534{
535    fn new(dev: &'a T, direction: Direction, channel: usize) -> Self {
536        Self {
537            dev,
538            direction,
539            channel,
540        }
541    }
542
543    fn ensure_available(&self) -> Result<(), Error> {
544        if self.dev.agc_available(self.direction, self.channel)? {
545            Ok(())
546        } else {
547            Err(Error::unsupported(Capability::Agc))
548        }
549    }
550
551    /// Return whether automatic gain control is enabled.
552    pub fn enabled(&self) -> Result<bool, Error> {
553        self.ensure_available()?;
554        self.dev.agc_enabled(self.direction, self.channel)
555    }
556
557    /// Enable automatic gain control.
558    pub fn enable(&self) -> Result<(), Error> {
559        self.set_enabled(true)
560    }
561
562    /// Disable automatic gain control.
563    pub fn disable(&self) -> Result<(), Error> {
564        self.set_enabled(false)
565    }
566
567    /// Set whether automatic gain control is enabled.
568    pub fn set_enabled(&self, enabled: bool) -> Result<(), Error> {
569        self.ensure_available()?;
570        self.dev
571            .set_agc_enabled(self.direction, self.channel, enabled)
572    }
573}
574
575/// Gain control handle for one channel.
576pub struct Gain<'a, T: GainControl + ?Sized> {
577    dev: &'a T,
578    direction: Direction,
579    channel: usize,
580}
581
582impl<'a, T> Gain<'a, T>
583where
584    T: GainControl + ?Sized,
585{
586    fn new(dev: &'a T, direction: Direction, channel: usize) -> Self {
587        Self {
588            dev,
589            direction,
590            channel,
591        }
592    }
593
594    /// Named gain elements.
595    pub fn elements(&self) -> Result<Vec<String>, Error> {
596        self.dev.gain_elements(self.direction, self.channel)
597    }
598
599    /// Overall gain.
600    pub fn value(&self) -> Result<Option<f64>, Error> {
601        self.dev.gain(self.direction, self.channel)
602    }
603
604    /// Set overall gain.
605    pub fn set(&self, gain: f64) -> Result<(), Error> {
606        self.dev.set_gain(self.direction, self.channel, gain)
607    }
608
609    /// Overall gain range.
610    pub fn range(&self) -> Result<Range, Error> {
611        self.dev.gain_range(self.direction, self.channel)
612    }
613
614    /// Named gain element handle.
615    pub fn element(&self, name: &str) -> GainElement<'a, T> {
616        GainElement {
617            dev: self.dev,
618            direction: self.direction,
619            channel: self.channel,
620            name: name.to_string(),
621        }
622    }
623}
624
625/// Gain element handle for one channel.
626pub struct GainElement<'a, T: GainControl + ?Sized> {
627    dev: &'a T,
628    direction: Direction,
629    channel: usize,
630    name: String,
631}
632
633impl<'a, T> GainElement<'a, T>
634where
635    T: GainControl + ?Sized,
636{
637    /// Gain element value.
638    pub fn value(&self) -> Result<Option<f64>, Error> {
639        self.dev
640            .gain_element(self.direction, self.channel, &self.name)
641    }
642
643    /// Set gain element value.
644    pub fn set(&self, gain: f64) -> Result<(), Error> {
645        self.dev
646            .set_gain_element(self.direction, self.channel, &self.name, gain)
647    }
648
649    /// Gain element range.
650    pub fn range(&self) -> Result<Range, Error> {
651        self.dev
652            .gain_element_range(self.direction, self.channel, &self.name)
653    }
654}
655
656/// Frequency control handle for one channel.
657pub struct Frequency<'a, T: FrequencyControl + ?Sized> {
658    dev: &'a T,
659    direction: Direction,
660    channel: usize,
661}
662
663impl<'a, T> Frequency<'a, T>
664where
665    T: FrequencyControl + ?Sized,
666{
667    fn new(dev: &'a T, direction: Direction, channel: usize) -> Self {
668        Self {
669            dev,
670            direction,
671            channel,
672        }
673    }
674
675    /// Overall frequency.
676    pub fn value(&self) -> Result<f64, Error> {
677        self.dev.frequency(self.direction, self.channel)
678    }
679
680    /// Set overall frequency.
681    pub fn set(&self, frequency: f64) -> Result<(), Error> {
682        self.set_with_args(frequency, Args::new())
683    }
684
685    /// Set overall frequency with driver arguments.
686    pub fn set_with_args(&self, frequency: f64, args: Args) -> Result<(), Error> {
687        self.dev
688            .set_frequency(self.direction, self.channel, frequency, args)
689    }
690
691    /// Overall frequency range.
692    pub fn range(&self) -> Result<Range, Error> {
693        self.dev.frequency_range(self.direction, self.channel)
694    }
695
696    /// Named frequency components.
697    pub fn components(&self) -> Result<Vec<String>, Error> {
698        self.dev.frequency_components(self.direction, self.channel)
699    }
700
701    /// Named frequency component handle.
702    pub fn component(&self, name: &str) -> FrequencyComponent<'a, T> {
703        FrequencyComponent {
704            dev: self.dev,
705            direction: self.direction,
706            channel: self.channel,
707            name: name.to_string(),
708        }
709    }
710}
711
712/// Frequency component handle for one channel.
713pub struct FrequencyComponent<'a, T: FrequencyControl + ?Sized> {
714    dev: &'a T,
715    direction: Direction,
716    channel: usize,
717    name: String,
718}
719
720impl<'a, T> FrequencyComponent<'a, T>
721where
722    T: FrequencyControl + ?Sized,
723{
724    /// Frequency component value.
725    pub fn value(&self) -> Result<f64, Error> {
726        self.dev
727            .component_frequency(self.direction, self.channel, &self.name)
728    }
729
730    /// Set frequency component value.
731    pub fn set(&self, frequency: f64) -> Result<(), Error> {
732        self.dev
733            .set_component_frequency(self.direction, self.channel, &self.name, frequency)
734    }
735
736    /// Frequency component range.
737    pub fn range(&self) -> Result<Range, Error> {
738        self.dev
739            .component_frequency_range(self.direction, self.channel, &self.name)
740    }
741}
742
743/// Sample-rate control handle for one channel.
744pub struct SampleRate<'a, T: SampleRateControl + ?Sized> {
745    dev: &'a T,
746    direction: Direction,
747    channel: usize,
748}
749
750impl<'a, T> SampleRate<'a, T>
751where
752    T: SampleRateControl + ?Sized,
753{
754    fn new(dev: &'a T, direction: Direction, channel: usize) -> Self {
755        Self {
756            dev,
757            direction,
758            channel,
759        }
760    }
761
762    /// Sample rate.
763    pub fn value(&self) -> Result<f64, Error> {
764        self.dev.sample_rate(self.direction, self.channel)
765    }
766
767    /// Set sample rate.
768    pub fn set(&self, rate: f64) -> Result<(), Error> {
769        self.dev.set_sample_rate(self.direction, self.channel, rate)
770    }
771
772    /// Sample-rate range.
773    pub fn range(&self) -> Result<Range, Error> {
774        self.dev.get_sample_rate_range(self.direction, self.channel)
775    }
776}
777
778/// Bandwidth control handle for one channel.
779pub struct Bandwidth<'a, T: BandwidthControl + ?Sized> {
780    dev: &'a T,
781    direction: Direction,
782    channel: usize,
783}
784
785impl<'a, T> Bandwidth<'a, T>
786where
787    T: BandwidthControl + ?Sized,
788{
789    fn new(dev: &'a T, direction: Direction, channel: usize) -> Self {
790        Self {
791            dev,
792            direction,
793            channel,
794        }
795    }
796
797    /// Bandwidth.
798    pub fn value(&self) -> Result<f64, Error> {
799        self.dev.bandwidth(self.direction, self.channel)
800    }
801
802    /// Set bandwidth.
803    pub fn set(&self, bandwidth: f64) -> Result<(), Error> {
804        self.dev
805            .set_bandwidth(self.direction, self.channel, bandwidth)
806    }
807
808    /// Bandwidth range.
809    pub fn range(&self) -> Result<Range, Error> {
810        self.dev.get_bandwidth_range(self.direction, self.channel)
811    }
812}
813
814/// Automatic DC offset correction handle for one channel.
815pub struct DcOffset<'a, T: DcOffsetControl + ?Sized> {
816    dev: &'a T,
817    direction: Direction,
818    channel: usize,
819}
820
821impl<'a, T> DcOffset<'a, T>
822where
823    T: DcOffsetControl + ?Sized,
824{
825    fn new(dev: &'a T, direction: Direction, channel: usize) -> Self {
826        Self {
827            dev,
828            direction,
829            channel,
830        }
831    }
832
833    fn ensure_available(&self) -> Result<(), Error> {
834        if self.dev.dc_offset_available(self.direction, self.channel)? {
835            Ok(())
836        } else {
837            Err(Error::unsupported(Capability::DcOffset))
838        }
839    }
840
841    /// Return whether automatic DC offset correction is enabled.
842    pub fn enabled(&self) -> Result<bool, Error> {
843        self.ensure_available()?;
844        self.dev.dc_offset_enabled(self.direction, self.channel)
845    }
846
847    /// Enable automatic DC offset correction.
848    pub fn enable(&self) -> Result<(), Error> {
849        self.set_enabled(true)
850    }
851
852    /// Disable automatic DC offset correction.
853    pub fn disable(&self) -> Result<(), Error> {
854        self.set_enabled(false)
855    }
856
857    /// Set whether automatic DC offset correction is enabled.
858    pub fn set_enabled(&self, enabled: bool) -> Result<(), Error> {
859        self.ensure_available()?;
860        self.dev
861            .set_dc_offset_enabled(self.direction, self.channel, enabled)
862    }
863}
864
865/// Wraps a driver implementation.
866///
867/// Implements a more ergonomic version of the backend APIs, e.g. using
868/// `Into<Args>`, which would not be possible in traits.
869#[derive(Clone)]
870pub struct Device<T> {
871    dev: T,
872}
873
874impl<T> Device<T> {
875    /// Create a device from the device implementation.
876    pub fn from_impl(dev: T) -> Self {
877        Self { dev }
878    }
879
880    /// Borrow the underlying device implementation.
881    pub fn as_inner(&self) -> &T {
882        &self.dev
883    }
884
885    /// Mutably borrow the underlying device implementation.
886    pub fn as_inner_mut(&mut self) -> &mut T {
887        &mut self.dev
888    }
889
890    /// Consume this device and return the underlying implementation.
891    pub fn into_inner(self) -> T {
892        self.dev
893    }
894}
895
896impl<T> Device<T>
897where
898    T: TypedDeviceBackend,
899{
900    /// Open a typed device matching `args`.
901    pub fn from_args<A: TryInto<Args>>(args: A) -> Result<Self, Error> {
902        let args = args
903            .try_into()
904            .map_err(|_| Error::invalid_argument("args", "failed to convert args"))?;
905        match args.get::<Driver>("driver") {
906            Ok(driver) if driver != <T as TypedDeviceBackend>::driver() => {
907                return Err(Error::DriverMismatch {
908                    expected: <T as TypedDeviceBackend>::driver(),
909                    requested: driver,
910                });
911            }
912            Ok(_) | Err(Error::MissingArgument { .. }) => {}
913            Err(e) => return Err(e),
914        }
915        Ok(Self::from_impl(T::open(&args)?))
916    }
917}
918
919impl<T> Device<T>
920where
921    T: DynDeviceBackend + 'static,
922{
923    /// Convert this typed device into a runtime-dispatched device.
924    pub fn erase(self) -> DynDevice {
925        DynDevice::from_impl(self.dev)
926    }
927}
928
929impl<T: DeviceInfo> Device<T> {
930    /// SDR [driver](Driver).
931    pub fn driver(&self) -> Driver {
932        self.dev.driver()
933    }
934
935    /// Identifier for the device, e.g. its serial.
936    pub fn id(&self) -> Result<String, Error> {
937        self.dev.id()
938    }
939
940    /// Device info that can be displayed to the user.
941    pub fn info(&self) -> Result<Args, Error> {
942        self.dev.info()
943    }
944
945    /// Borrow the underlying device implementation as type `D`.
946    pub fn impl_ref<D: DeviceInfo + 'static>(&self) -> Result<&D, Error> {
947        self.dev
948            .as_any()
949            .downcast_ref::<D>()
950            .ok_or_else(|| Error::invalid_argument("type", "device implementation type mismatch"))
951    }
952
953    /// Mutably borrow the underlying device implementation as type `D`.
954    pub fn impl_mut<D: DeviceInfo + 'static>(&mut self) -> Result<&mut D, Error> {
955        self.dev
956            .as_any_mut()
957            .downcast_mut::<D>()
958            .ok_or_else(|| Error::invalid_argument("type", "device implementation type mismatch"))
959    }
960}
961
962impl DynDevice {
963    /// Open the first discovered runtime-dispatched device.
964    pub fn new() -> Result<Self, Error> {
965        let registry = Registry::default();
966        let descriptors = registry.probe(Args::new())?;
967        let descriptor = descriptors.first().ok_or(Error::DeviceNotFound)?;
968        registry.open(descriptor)
969    }
970
971    /// Open a runtime-dispatched device matching `args`.
972    pub fn from_args<A: TryInto<Args>>(args: A) -> Result<Self, Error> {
973        Registry::default().open_args(args)
974    }
975
976    /// Create a runtime-dispatched device from a concrete implementation.
977    pub fn from_impl<T: DynDeviceBackend + 'static>(dev: T) -> Self {
978        Self {
979            inner: Arc::new(dev),
980        }
981    }
982
983    /// Borrow the erased backend.
984    pub fn as_backend(&self) -> &dyn DynDeviceBackend {
985        self.inner.as_ref()
986    }
987
988    /// Try to downcast to a concrete device implementation.
989    pub fn downcast_ref<D: DeviceInfo + 'static>(&self) -> Option<&D> {
990        self.inner.as_any().downcast_ref::<D>()
991    }
992
993    /// Try to downcast mutably to a concrete device implementation.
994    pub fn downcast_mut<D: DeviceInfo + 'static>(&mut self) -> Option<&mut D> {
995        Arc::get_mut(&mut self.inner)?
996            .as_any_mut()
997            .downcast_mut::<D>()
998    }
999
1000    /// SDR [driver](Driver).
1001    pub fn driver(&self) -> Driver {
1002        self.inner.driver()
1003    }
1004
1005    /// Identifier for the device, e.g. its serial.
1006    pub fn id(&self) -> Result<String, Error> {
1007        self.inner.id()
1008    }
1009
1010    /// Device info that can be displayed to the user.
1011    pub fn info(&self) -> Result<Args, Error> {
1012        self.inner.info()
1013    }
1014
1015    /// Structured runtime capabilities for the device.
1016    pub fn capabilities(&self) -> Result<DeviceCapabilities, Error> {
1017        self.inner.capabilities()
1018    }
1019
1020    /// RX channel handle.
1021    pub fn rx(&self, index: usize) -> Result<RxChannel<'_, Self>, Error> {
1022        ensure_channel(self, Direction::Rx, index)?;
1023        Ok(RxChannel::new(self, index))
1024    }
1025
1026    /// TX channel handle.
1027    pub fn tx(&self, index: usize) -> Result<TxChannel<'_, Self>, Error> {
1028        ensure_channel(self, Direction::Tx, index)?;
1029        Ok(TxChannel::new(self, index))
1030    }
1031
1032    /// Create an RX streamer.
1033    pub fn rx_streamer(&self, channels: &[usize]) -> Result<DynRxStreamer, Error> {
1034        self.rx_streamer_with_args(channels, Args::new())
1035    }
1036
1037    /// Create an RX streamer, using `args`.
1038    pub fn rx_streamer_with_args<A: TryInto<Args>>(
1039        &self,
1040        channels: &[usize],
1041        args: A,
1042    ) -> Result<DynRxStreamer, Error> {
1043        for channel in channels {
1044            ensure_channel(self, Direction::Rx, *channel)?;
1045        }
1046        <Self as RxDevice>::rx_streamer(
1047            self,
1048            channels,
1049            args.try_into()
1050                .map_err(|_| Error::invalid_argument("args", "failed to convert args"))?,
1051        )
1052    }
1053
1054    /// Create a TX streamer.
1055    pub fn tx_streamer(&self, channels: &[usize]) -> Result<DynTxStreamer, Error> {
1056        self.tx_streamer_with_args(channels, Args::new())
1057    }
1058
1059    /// Create a TX streamer, using `args`.
1060    pub fn tx_streamer_with_args<A: TryInto<Args>>(
1061        &self,
1062        channels: &[usize],
1063        args: A,
1064    ) -> Result<DynTxStreamer, Error> {
1065        for channel in channels {
1066            ensure_channel(self, Direction::Tx, *channel)?;
1067        }
1068        <Self as TxDevice>::tx_streamer(
1069            self,
1070            channels,
1071            args.try_into()
1072                .map_err(|_| Error::invalid_argument("args", "failed to convert args"))?,
1073        )
1074    }
1075}
1076
1077impl DeviceInfo for DynDevice {
1078    fn as_any(&self) -> &dyn Any {
1079        self
1080    }
1081
1082    fn as_any_mut(&mut self) -> &mut dyn Any {
1083        self
1084    }
1085
1086    fn driver(&self) -> Driver {
1087        self.inner.driver()
1088    }
1089    fn id(&self) -> Result<String, Error> {
1090        self.inner.id()
1091    }
1092    fn info(&self) -> Result<Args, Error> {
1093        self.inner.info()
1094    }
1095}
1096
1097impl ChannelInfo for DynDevice {
1098    fn num_channels(&self, direction: Direction) -> Result<usize, Error> {
1099        self.inner
1100            .as_ref()
1101            .channel_info()
1102            .ok_or_else(|| Error::unsupported(Capability::ChannelInfo))?
1103            .num_channels(direction)
1104    }
1105    fn full_duplex(&self, direction: Direction, channel: usize) -> Result<bool, Error> {
1106        self.inner
1107            .as_ref()
1108            .channel_info()
1109            .ok_or_else(|| Error::unsupported(Capability::ChannelInfo))?
1110            .full_duplex(direction, channel)
1111    }
1112}
1113
1114impl RxDevice for DynDevice {
1115    type RxStreamer = DynRxStreamer;
1116
1117    fn rx_streamer(&self, channels: &[usize], args: Args) -> Result<Self::RxStreamer, Error> {
1118        self.inner
1119            .as_ref()
1120            .rx_device()
1121            .ok_or_else(|| Error::unsupported(Capability::RxStreaming))?
1122            .rx_streamer(channels, args)
1123    }
1124}
1125
1126impl TxDevice for DynDevice {
1127    type TxStreamer = DynTxStreamer;
1128
1129    fn tx_streamer(&self, channels: &[usize], args: Args) -> Result<Self::TxStreamer, Error> {
1130        self.inner
1131            .as_ref()
1132            .tx_device()
1133            .ok_or_else(|| Error::unsupported(Capability::TxStreaming))?
1134            .tx_streamer(channels, args)
1135    }
1136}
1137
1138impl AntennaControl for DynDevice {
1139    fn antennas(&self, direction: Direction, channel: usize) -> Result<Vec<String>, Error> {
1140        self.inner
1141            .as_ref()
1142            .antenna_control()
1143            .ok_or_else(|| Error::unsupported(Capability::Antenna))?
1144            .antennas(direction, channel)
1145    }
1146
1147    fn antenna(&self, direction: Direction, channel: usize) -> Result<String, Error> {
1148        self.inner
1149            .as_ref()
1150            .antenna_control()
1151            .ok_or_else(|| Error::unsupported(Capability::Antenna))?
1152            .antenna(direction, channel)
1153    }
1154
1155    fn set_antenna(&self, direction: Direction, channel: usize, name: &str) -> Result<(), Error> {
1156        self.inner
1157            .as_ref()
1158            .antenna_control()
1159            .ok_or_else(|| Error::unsupported(Capability::Antenna))?
1160            .set_antenna(direction, channel, name)
1161    }
1162}
1163
1164impl GainControl for DynDevice {
1165    fn gain_elements(&self, direction: Direction, channel: usize) -> Result<Vec<String>, Error> {
1166        self.inner
1167            .as_ref()
1168            .gain_control()
1169            .ok_or_else(|| Error::unsupported(Capability::Gain))?
1170            .gain_elements(direction, channel)
1171    }
1172
1173    fn set_gain(&self, direction: Direction, channel: usize, gain: f64) -> Result<(), Error> {
1174        self.inner
1175            .as_ref()
1176            .gain_control()
1177            .ok_or_else(|| Error::unsupported(Capability::Gain))?
1178            .set_gain(direction, channel, gain)
1179    }
1180
1181    fn gain(&self, direction: Direction, channel: usize) -> Result<Option<f64>, Error> {
1182        self.inner
1183            .as_ref()
1184            .gain_control()
1185            .ok_or_else(|| Error::unsupported(Capability::Gain))?
1186            .gain(direction, channel)
1187    }
1188
1189    fn gain_range(&self, direction: Direction, channel: usize) -> Result<Range, Error> {
1190        self.inner
1191            .as_ref()
1192            .gain_control()
1193            .ok_or_else(|| Error::unsupported(Capability::Gain))?
1194            .gain_range(direction, channel)
1195    }
1196
1197    fn set_gain_element(
1198        &self,
1199        direction: Direction,
1200        channel: usize,
1201        name: &str,
1202        gain: f64,
1203    ) -> Result<(), Error> {
1204        self.inner
1205            .as_ref()
1206            .gain_control()
1207            .ok_or_else(|| Error::unsupported(Capability::Gain))?
1208            .set_gain_element(direction, channel, name, gain)
1209    }
1210
1211    fn gain_element(
1212        &self,
1213        direction: Direction,
1214        channel: usize,
1215        name: &str,
1216    ) -> Result<Option<f64>, Error> {
1217        self.inner
1218            .as_ref()
1219            .gain_control()
1220            .ok_or_else(|| Error::unsupported(Capability::Gain))?
1221            .gain_element(direction, channel, name)
1222    }
1223
1224    fn gain_element_range(
1225        &self,
1226        direction: Direction,
1227        channel: usize,
1228        name: &str,
1229    ) -> Result<Range, Error> {
1230        self.inner
1231            .as_ref()
1232            .gain_control()
1233            .ok_or_else(|| Error::unsupported(Capability::Gain))?
1234            .gain_element_range(direction, channel, name)
1235    }
1236}
1237
1238impl FrequencyControl for DynDevice {
1239    fn frequency_range(&self, direction: Direction, channel: usize) -> Result<Range, Error> {
1240        self.inner
1241            .as_ref()
1242            .frequency_control()
1243            .ok_or_else(|| Error::unsupported(Capability::Frequency))?
1244            .frequency_range(direction, channel)
1245    }
1246
1247    fn frequency(&self, direction: Direction, channel: usize) -> Result<f64, Error> {
1248        self.inner
1249            .as_ref()
1250            .frequency_control()
1251            .ok_or_else(|| Error::unsupported(Capability::Frequency))?
1252            .frequency(direction, channel)
1253    }
1254
1255    fn set_frequency(
1256        &self,
1257        direction: Direction,
1258        channel: usize,
1259        frequency: f64,
1260        args: Args,
1261    ) -> Result<(), Error> {
1262        self.inner
1263            .as_ref()
1264            .frequency_control()
1265            .ok_or_else(|| Error::unsupported(Capability::Frequency))?
1266            .set_frequency(direction, channel, frequency, args)
1267    }
1268
1269    fn frequency_components(
1270        &self,
1271        direction: Direction,
1272        channel: usize,
1273    ) -> Result<Vec<String>, Error> {
1274        self.inner
1275            .as_ref()
1276            .frequency_control()
1277            .ok_or_else(|| Error::unsupported(Capability::Frequency))?
1278            .frequency_components(direction, channel)
1279    }
1280
1281    fn component_frequency_range(
1282        &self,
1283        direction: Direction,
1284        channel: usize,
1285        name: &str,
1286    ) -> Result<Range, Error> {
1287        self.inner
1288            .as_ref()
1289            .frequency_control()
1290            .ok_or_else(|| Error::unsupported(Capability::Frequency))?
1291            .component_frequency_range(direction, channel, name)
1292    }
1293
1294    fn component_frequency(
1295        &self,
1296        direction: Direction,
1297        channel: usize,
1298        name: &str,
1299    ) -> Result<f64, Error> {
1300        self.inner
1301            .as_ref()
1302            .frequency_control()
1303            .ok_or_else(|| Error::unsupported(Capability::Frequency))?
1304            .component_frequency(direction, channel, name)
1305    }
1306
1307    fn set_component_frequency(
1308        &self,
1309        direction: Direction,
1310        channel: usize,
1311        name: &str,
1312        frequency: f64,
1313    ) -> Result<(), Error> {
1314        self.inner
1315            .as_ref()
1316            .frequency_control()
1317            .ok_or_else(|| Error::unsupported(Capability::Frequency))?
1318            .set_component_frequency(direction, channel, name, frequency)
1319    }
1320}
1321
1322impl SampleRateControl for DynDevice {
1323    fn sample_rate(&self, direction: Direction, channel: usize) -> Result<f64, Error> {
1324        self.inner
1325            .as_ref()
1326            .sample_rate_control()
1327            .ok_or_else(|| Error::unsupported(Capability::SampleRate))?
1328            .sample_rate(direction, channel)
1329    }
1330
1331    fn set_sample_rate(
1332        &self,
1333        direction: Direction,
1334        channel: usize,
1335        rate: f64,
1336    ) -> Result<(), Error> {
1337        self.inner
1338            .as_ref()
1339            .sample_rate_control()
1340            .ok_or_else(|| Error::unsupported(Capability::SampleRate))?
1341            .set_sample_rate(direction, channel, rate)
1342    }
1343
1344    fn get_sample_rate_range(&self, direction: Direction, channel: usize) -> Result<Range, Error> {
1345        self.inner
1346            .as_ref()
1347            .sample_rate_control()
1348            .ok_or_else(|| Error::unsupported(Capability::SampleRate))?
1349            .get_sample_rate_range(direction, channel)
1350    }
1351}
1352
1353impl BandwidthControl for DynDevice {
1354    fn bandwidth(&self, direction: Direction, channel: usize) -> Result<f64, Error> {
1355        self.inner
1356            .as_ref()
1357            .bandwidth_control()
1358            .ok_or_else(|| Error::unsupported(Capability::Bandwidth))?
1359            .bandwidth(direction, channel)
1360    }
1361
1362    fn set_bandwidth(&self, direction: Direction, channel: usize, bw: f64) -> Result<(), Error> {
1363        self.inner
1364            .as_ref()
1365            .bandwidth_control()
1366            .ok_or_else(|| Error::unsupported(Capability::Bandwidth))?
1367            .set_bandwidth(direction, channel, bw)
1368    }
1369
1370    fn get_bandwidth_range(&self, direction: Direction, channel: usize) -> Result<Range, Error> {
1371        self.inner
1372            .as_ref()
1373            .bandwidth_control()
1374            .ok_or_else(|| Error::unsupported(Capability::Bandwidth))?
1375            .get_bandwidth_range(direction, channel)
1376    }
1377}
1378
1379impl AgcControl for DynDevice {
1380    fn agc_available(&self, direction: Direction, channel: usize) -> Result<bool, Error> {
1381        self.inner
1382            .as_ref()
1383            .agc_control()
1384            .ok_or_else(|| Error::unsupported(Capability::Agc))?
1385            .agc_available(direction, channel)
1386    }
1387
1388    fn agc_enabled(&self, direction: Direction, channel: usize) -> Result<bool, Error> {
1389        self.inner
1390            .as_ref()
1391            .agc_control()
1392            .ok_or_else(|| Error::unsupported(Capability::Agc))?
1393            .agc_enabled(direction, channel)
1394    }
1395
1396    fn set_agc_enabled(
1397        &self,
1398        direction: Direction,
1399        channel: usize,
1400        enabled: bool,
1401    ) -> Result<(), Error> {
1402        self.inner
1403            .as_ref()
1404            .agc_control()
1405            .ok_or_else(|| Error::unsupported(Capability::Agc))?
1406            .set_agc_enabled(direction, channel, enabled)
1407    }
1408}
1409
1410impl DcOffsetControl for DynDevice {
1411    fn dc_offset_available(&self, direction: Direction, channel: usize) -> Result<bool, Error> {
1412        self.inner
1413            .as_ref()
1414            .dc_offset_control()
1415            .ok_or_else(|| Error::unsupported(Capability::DcOffset))?
1416            .dc_offset_available(direction, channel)
1417    }
1418
1419    fn dc_offset_enabled(&self, direction: Direction, channel: usize) -> Result<bool, Error> {
1420        self.inner
1421            .as_ref()
1422            .dc_offset_control()
1423            .ok_or_else(|| Error::unsupported(Capability::DcOffset))?
1424            .dc_offset_enabled(direction, channel)
1425    }
1426
1427    fn set_dc_offset_enabled(
1428        &self,
1429        direction: Direction,
1430        channel: usize,
1431        enabled: bool,
1432    ) -> Result<(), Error> {
1433        self.inner
1434            .as_ref()
1435            .dc_offset_control()
1436            .ok_or_else(|| Error::unsupported(Capability::DcOffset))?
1437            .set_dc_offset_enabled(direction, channel, enabled)
1438    }
1439}
1440
1441impl<T: ChannelInfo> Device<T> {
1442    /// RX channel handle.
1443    pub fn rx(&self, index: usize) -> Result<RxChannel<'_, T>, Error> {
1444        ensure_channel(&self.dev, Direction::Rx, index)?;
1445        Ok(RxChannel::new(&self.dev, index))
1446    }
1447
1448    /// TX channel handle.
1449    pub fn tx(&self, index: usize) -> Result<TxChannel<'_, T>, Error> {
1450        ensure_channel(&self.dev, Direction::Tx, index)?;
1451        Ok(TxChannel::new(&self.dev, index))
1452    }
1453}
1454
1455fn ensure_channel<T>(dev: &T, direction: Direction, channel: usize) -> Result<(), Error>
1456where
1457    T: ChannelInfo + ?Sized,
1458{
1459    let available = dev.num_channels(direction)?;
1460    if channel < available {
1461        Ok(())
1462    } else {
1463        Err(Error::invalid_channel(direction, channel, available))
1464    }
1465}
1466
1467impl<T: RxDevice + ChannelInfo> Device<T> {
1468    /// Create an RX streamer over one or more RX channels.
1469    pub fn rx_streamer(&self, channels: &[usize]) -> Result<T::RxStreamer, Error> {
1470        self.rx_streamer_with_args(channels, Args::new())
1471    }
1472
1473    /// Create an RX streamer over one or more RX channels, using `args`.
1474    pub fn rx_streamer_with_args(
1475        &self,
1476        channels: &[usize],
1477        args: Args,
1478    ) -> Result<T::RxStreamer, Error> {
1479        for channel in channels {
1480            ensure_channel(&self.dev, Direction::Rx, *channel)?;
1481        }
1482        self.dev.rx_streamer(channels, args)
1483    }
1484}
1485
1486impl<T: TxDevice + ChannelInfo> Device<T> {
1487    /// Create a TX streamer over one or more TX channels.
1488    pub fn tx_streamer(&self, channels: &[usize]) -> Result<T::TxStreamer, Error> {
1489        self.tx_streamer_with_args(channels, Args::new())
1490    }
1491
1492    /// Create a TX streamer over one or more TX channels, using `args`.
1493    pub fn tx_streamer_with_args(
1494        &self,
1495        channels: &[usize],
1496        args: Args,
1497    ) -> Result<T::TxStreamer, Error> {
1498        for channel in channels {
1499            ensure_channel(&self.dev, Direction::Tx, *channel)?;
1500        }
1501        self.dev.tx_streamer(channels, args)
1502    }
1503}
1504
1505impl<'a, T: RxDevice + ?Sized> RxChannel<'a, T> {
1506    /// Create a single-channel RX streamer.
1507    pub fn streamer(&self) -> Result<T::RxStreamer, Error> {
1508        self.streamer_with_args(Args::new())
1509    }
1510
1511    /// Create a single-channel RX streamer, using `args`.
1512    pub fn streamer_with_args(&self, args: Args) -> Result<T::RxStreamer, Error> {
1513        self.dev.rx_streamer(&[self.channel], args)
1514    }
1515}
1516
1517impl<'a, T: TxDevice + ?Sized> TxChannel<'a, T> {
1518    /// Create a single-channel TX streamer.
1519    pub fn streamer(&self) -> Result<T::TxStreamer, Error> {
1520        self.streamer_with_args(Args::new())
1521    }
1522
1523    /// Create a single-channel TX streamer, using `args`.
1524    pub fn streamer_with_args(&self, args: Args) -> Result<T::TxStreamer, Error> {
1525        self.dev.tx_streamer(&[self.channel], args)
1526    }
1527}
1528
1529impl<'a, T: ChannelInfo + ?Sized> RxChannel<'a, T> {
1530    /// Full-duplex support for this RX channel.
1531    pub fn full_duplex(&self) -> Result<bool, Error> {
1532        self.dev.full_duplex(Direction::Rx, self.channel)
1533    }
1534}
1535
1536impl<'a, T: ChannelInfo + ?Sized> TxChannel<'a, T> {
1537    /// Full-duplex support for this TX channel.
1538    pub fn full_duplex(&self) -> Result<bool, Error> {
1539        self.dev.full_duplex(Direction::Tx, self.channel)
1540    }
1541}
1542
1543macro_rules! impl_channel_controls {
1544    ($channel:ident, $direction:expr) => {
1545        impl<'a, T: AntennaControl + ?Sized> $channel<'a, T> {
1546            /// Antenna control.
1547            pub fn antenna(&self) -> Antenna<'_, T> {
1548                Antenna::new(self.dev, $direction, self.channel)
1549            }
1550        }
1551
1552        impl<'a, T: AgcControl + ?Sized> $channel<'a, T> {
1553            /// Automatic gain control.
1554            pub fn agc(&self) -> Agc<'_, T> {
1555                Agc::new(self.dev, $direction, self.channel)
1556            }
1557        }
1558
1559        impl<'a, T: GainControl + ?Sized> $channel<'a, T> {
1560            /// Gain control.
1561            pub fn gain(&self) -> Gain<'_, T> {
1562                Gain::new(self.dev, $direction, self.channel)
1563            }
1564        }
1565
1566        impl<'a, T: FrequencyControl + ?Sized> $channel<'a, T> {
1567            /// Frequency control.
1568            pub fn frequency(&self) -> Frequency<'_, T> {
1569                Frequency::new(self.dev, $direction, self.channel)
1570            }
1571        }
1572
1573        impl<'a, T: SampleRateControl + ?Sized> $channel<'a, T> {
1574            /// Sample-rate control.
1575            pub fn sample_rate(&self) -> SampleRate<'_, T> {
1576                SampleRate::new(self.dev, $direction, self.channel)
1577            }
1578        }
1579
1580        impl<'a, T: BandwidthControl + ?Sized> $channel<'a, T> {
1581            /// Bandwidth control.
1582            pub fn bandwidth(&self) -> Bandwidth<'_, T> {
1583                Bandwidth::new(self.dev, $direction, self.channel)
1584            }
1585        }
1586
1587        impl<'a, T: DcOffsetControl + ?Sized> $channel<'a, T> {
1588            /// Automatic DC offset correction.
1589            pub fn dc_offset(&self) -> DcOffset<'_, T> {
1590                DcOffset::new(self.dev, $direction, self.channel)
1591            }
1592        }
1593    };
1594}
1595
1596impl_channel_controls!(RxChannel, Direction::Rx);
1597impl_channel_controls!(TxChannel, Direction::Tx);
1598
1599#[cfg(all(test, feature = "dummy"))]
1600mod tests {
1601    use super::*;
1602
1603    struct RxOnly;
1604
1605    struct DcToggle(std::sync::Mutex<bool>);
1606
1607    struct TestRxStreamer;
1608
1609    impl DeviceInfo for RxOnly {
1610        fn as_any(&self) -> &dyn Any {
1611            self
1612        }
1613
1614        fn as_any_mut(&mut self) -> &mut dyn Any {
1615            self
1616        }
1617
1618        fn driver(&self) -> Driver {
1619            Driver::Dummy
1620        }
1621
1622        fn id(&self) -> Result<String, Error> {
1623            Ok("rx-only".to_string())
1624        }
1625
1626        fn info(&self) -> Result<Args, Error> {
1627            Ok(Args::new())
1628        }
1629    }
1630
1631    impl DynDeviceBackend for RxOnly {
1632        fn channel_info(&self) -> Option<&dyn ChannelInfo> {
1633            Some(self)
1634        }
1635
1636        fn rx_device(&self) -> Option<&dyn ErasedRxDevice> {
1637            Some(self)
1638        }
1639    }
1640
1641    impl ChannelInfo for RxOnly {
1642        fn num_channels(&self, direction: Direction) -> Result<usize, Error> {
1643            match direction {
1644                Direction::Rx => Ok(1),
1645                Direction::Tx => Ok(0),
1646            }
1647        }
1648
1649        fn full_duplex(&self, _direction: Direction, _channel: usize) -> Result<bool, Error> {
1650            Ok(false)
1651        }
1652    }
1653
1654    impl RxDevice for RxOnly {
1655        type RxStreamer = TestRxStreamer;
1656
1657        fn rx_streamer(&self, channels: &[usize], _args: Args) -> Result<Self::RxStreamer, Error> {
1658            match channels {
1659                &[0] => Ok(TestRxStreamer),
1660                _ => Err(Error::invalid_argument(
1661                    "channels",
1662                    "unsupported RX channel set",
1663                )),
1664            }
1665        }
1666    }
1667
1668    impl DcOffsetControl for DcToggle {
1669        fn dc_offset_available(
1670            &self,
1671            _direction: Direction,
1672            channel: usize,
1673        ) -> Result<bool, Error> {
1674            if channel == 0 {
1675                Ok(true)
1676            } else {
1677                Err(Error::invalid_channel(Direction::Rx, channel, 1))
1678            }
1679        }
1680
1681        fn dc_offset_enabled(&self, _direction: Direction, channel: usize) -> Result<bool, Error> {
1682            if channel == 0 {
1683                Ok(*self.0.lock().unwrap())
1684            } else {
1685                Err(Error::invalid_channel(Direction::Rx, channel, 1))
1686            }
1687        }
1688
1689        fn set_dc_offset_enabled(
1690            &self,
1691            _direction: Direction,
1692            channel: usize,
1693            enabled: bool,
1694        ) -> Result<(), Error> {
1695            if channel == 0 {
1696                *self.0.lock().unwrap() = enabled;
1697                Ok(())
1698            } else {
1699                Err(Error::invalid_channel(Direction::Rx, channel, 1))
1700            }
1701        }
1702    }
1703
1704    impl crate::RxStreamer for TestRxStreamer {
1705        fn mtu(&self) -> Result<usize, Error> {
1706            Ok(1)
1707        }
1708
1709        fn activate_at(&mut self, _time_ns: Option<i64>) -> Result<(), Error> {
1710            Ok(())
1711        }
1712
1713        fn deactivate_at(&mut self, _time_ns: Option<i64>) -> Result<(), Error> {
1714            Ok(())
1715        }
1716
1717        fn read(
1718            &mut self,
1719            _buffers: &mut [&mut [num_complex::Complex32]],
1720            _timeout_us: i64,
1721        ) -> Result<usize, Error> {
1722            Ok(0)
1723        }
1724    }
1725
1726    #[test]
1727    fn dyn_device_reports_capabilities() {
1728        let dummy = crate::impls::Dummy::open(Args::new()).unwrap();
1729        let dev = DynDevice::from_impl(dummy);
1730
1731        let capabilities = dev.capabilities().unwrap();
1732
1733        assert_eq!(capabilities.rx_channels.len(), 1);
1734        assert_eq!(capabilities.tx_channels.len(), 1);
1735
1736        let rx0 = &capabilities.rx_channels[0];
1737        assert_eq!(rx0.channel, 0);
1738        assert_eq!(rx0.full_duplex, Some(true));
1739        assert_eq!(rx0.controls.antennas, Some(vec!["A".to_string()]));
1740        assert!(rx0.controls.agc);
1741        assert_eq!(rx0.controls.gain_elements, Some(vec!["RF".to_string()]));
1742        assert_eq!(
1743            rx0.controls.frequency_components,
1744            Some(vec!["freq".to_string()])
1745        );
1746        assert!(!rx0.controls.dc_offset);
1747    }
1748
1749    #[test]
1750    fn antenna_handle_reports_ports_and_selected_port() {
1751        let dummy = crate::impls::Dummy::open(Args::new()).unwrap();
1752        let dev = Device::from_impl(dummy);
1753        let rx0 = dev.rx(0).unwrap();
1754        let antenna = rx0.antenna();
1755
1756        assert_eq!(antenna.ports().unwrap(), vec![String::from("A")]);
1757        assert_eq!(antenna.selected().unwrap(), "A");
1758        antenna.select("A").unwrap();
1759    }
1760
1761    #[test]
1762    fn typed_device_erases_to_dyn_device_and_downcasts() {
1763        let dummy = crate::impls::Dummy::open(Args::new()).unwrap();
1764        let dev = Device::from_impl(dummy);
1765        let mut dev = dev.erase();
1766
1767        assert_eq!(dev.driver(), Driver::Dummy);
1768        assert!(dev.downcast_ref::<crate::impls::Dummy>().is_some());
1769        assert!(dev.downcast_mut::<crate::impls::Dummy>().is_some());
1770    }
1771
1772    #[test]
1773    fn agc_handle_controls_enabled_state() {
1774        let dummy = crate::impls::Dummy::open(Args::new()).unwrap();
1775        let dev = Device::from_impl(dummy);
1776        let rx0 = dev.rx(0).unwrap();
1777        let agc = rx0.agc();
1778
1779        agc.enable().unwrap();
1780        assert!(agc.enabled().unwrap());
1781
1782        agc.disable().unwrap();
1783        assert!(!agc.enabled().unwrap());
1784    }
1785
1786    #[test]
1787    fn dc_offset_handle_controls_enabled_state() {
1788        let dev = Device::from_impl(DcToggle(std::sync::Mutex::new(false)));
1789        let rx0 = RxChannel::new(&dev.dev, 0);
1790        let dc_offset = rx0.dc_offset();
1791
1792        dc_offset.enable().unwrap();
1793        assert!(dc_offset.enabled().unwrap());
1794
1795        dc_offset.disable().unwrap();
1796        assert!(!dc_offset.enabled().unwrap());
1797    }
1798
1799    #[test]
1800    fn dyn_device_does_not_require_all_capabilities() {
1801        let dev = DynDevice::from_impl(RxOnly);
1802
1803        let capabilities = dev.capabilities().unwrap();
1804        assert_eq!(capabilities.rx_channels.len(), 1);
1805        assert_eq!(capabilities.tx_channels.len(), 0);
1806        assert_eq!(
1807            capabilities.rx_channels[0].controls,
1808            ChannelControls::default()
1809        );
1810
1811        assert!(dev.rx_streamer(&[0]).is_ok());
1812        assert!(matches!(
1813            dev.tx(0),
1814            Err(Error::InvalidChannel {
1815                direction: Direction::Tx,
1816                channel: 0,
1817                available: 0
1818            })
1819        ));
1820        let rx0 = dev.rx(0).unwrap();
1821        let agc = rx0.agc();
1822        assert!(matches!(
1823            agc.enabled(),
1824            Err(Error::Unsupported {
1825                capability: Capability::Agc,
1826                ..
1827            })
1828        ));
1829        let dc_offset = rx0.dc_offset();
1830        assert!(matches!(
1831            dc_offset.enabled(),
1832            Err(Error::Unsupported {
1833                capability: Capability::DcOffset,
1834                ..
1835            })
1836        ));
1837    }
1838}