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
18pub type DynRxStreamer = Box<dyn RxStreamer>;
20
21pub type DynTxStreamer = Box<dyn TxStreamer>;
23
24pub trait ErasedRxDevice {
26 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
40pub trait ErasedTxDevice {
42 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
56pub trait DynDeviceBackend: DeviceInfo + Send + Sync {
62 fn capabilities(&self) -> Result<DeviceCapabilities, Error> {
64 DeviceCapabilities::from_dyn(self)
65 }
66
67 fn channel_info(&self) -> Option<&dyn ChannelInfo> {
69 None
70 }
71
72 fn rx_device(&self) -> Option<&dyn ErasedRxDevice> {
74 None
75 }
76
77 fn tx_device(&self) -> Option<&dyn ErasedTxDevice> {
79 None
80 }
81
82 fn antenna_control(&self) -> Option<&dyn AntennaControl> {
84 None
85 }
86
87 fn agc_control(&self) -> Option<&dyn AgcControl> {
89 None
90 }
91
92 fn gain_control(&self) -> Option<&dyn GainControl> {
94 None
95 }
96
97 fn frequency_control(&self) -> Option<&dyn FrequencyControl> {
99 None
100 }
101
102 fn sample_rate_control(&self) -> Option<&dyn SampleRateControl> {
104 None
105 }
106
107 fn bandwidth_control(&self) -> Option<&dyn BandwidthControl> {
109 None
110 }
111
112 fn dc_offset_control(&self) -> Option<&dyn DcOffsetControl> {
114 None
115 }
116}
117
118#[derive(Clone)]
123pub struct DynDevice {
124 inner: Arc<dyn DynDeviceBackend>,
125}
126
127#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct DeviceCapabilities {
130 pub rx_channels: Vec<ChannelCapabilities>,
132 pub tx_channels: Vec<ChannelCapabilities>,
134}
135
136impl DeviceCapabilities {
137 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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
148pub struct ChannelCapabilities {
149 pub channel: usize,
151 pub full_duplex: Option<bool>,
153 pub controls: ChannelControls,
155}
156
157#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
159pub struct ChannelControls {
160 pub antennas: Option<Vec<String>>,
162 pub agc: bool,
164 pub gain_elements: Option<Vec<String>>,
166 pub gain_range: Option<Range>,
168 pub frequency_components: Option<Vec<String>>,
170 pub frequency_range: Option<Range>,
172 pub sample_rate_range: Option<Range>,
174 pub bandwidth_range: Option<Range>,
176 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
266pub trait DeviceInfo {
268 fn as_any(&self) -> &dyn Any;
270 fn as_any_mut(&mut self) -> &mut dyn Any;
272 fn driver(&self) -> Driver;
274 fn id(&self) -> Result<String, Error>;
276 fn info(&self) -> Result<Args, Error>;
278}
279
280pub trait ChannelInfo {
282 fn num_channels(&self, direction: Direction) -> Result<usize, Error>;
284 fn full_duplex(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
286}
287
288pub trait RxDevice {
290 type RxStreamer: RxStreamer;
292
293 fn rx_streamer(&self, channels: &[usize], args: Args) -> Result<Self::RxStreamer, Error>;
295}
296
297pub trait TxDevice {
299 type TxStreamer: TxStreamer;
301
302 fn tx_streamer(&self, channels: &[usize], args: Args) -> Result<Self::TxStreamer, Error>;
304}
305
306pub trait AntennaControl {
308 fn antennas(&self, direction: Direction, channel: usize) -> Result<Vec<String>, Error>;
310 fn antenna(&self, direction: Direction, channel: usize) -> Result<String, Error>;
312 fn set_antenna(&self, direction: Direction, channel: usize, name: &str) -> Result<(), Error>;
314}
315
316pub trait AgcControl {
318 fn agc_available(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
320 fn agc_enabled(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
322 fn set_agc_enabled(
324 &self,
325 direction: Direction,
326 channel: usize,
327 enabled: bool,
328 ) -> Result<(), Error>;
329}
330
331pub trait GainControl {
333 fn gain_elements(&self, direction: Direction, channel: usize) -> Result<Vec<String>, Error>;
335 fn set_gain(&self, direction: Direction, channel: usize, gain: f64) -> Result<(), Error>;
337 fn gain(&self, direction: Direction, channel: usize) -> Result<Option<f64>, Error>;
339 fn gain_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
341 fn set_gain_element(
343 &self,
344 direction: Direction,
345 channel: usize,
346 name: &str,
347 gain: f64,
348 ) -> Result<(), Error>;
349 fn gain_element(
351 &self,
352 direction: Direction,
353 channel: usize,
354 name: &str,
355 ) -> Result<Option<f64>, Error>;
356 fn gain_element_range(
358 &self,
359 direction: Direction,
360 channel: usize,
361 name: &str,
362 ) -> Result<Range, Error>;
363}
364
365pub trait FrequencyControl {
367 fn frequency_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
369 fn frequency(&self, direction: Direction, channel: usize) -> Result<f64, Error>;
371 fn set_frequency(
373 &self,
374 direction: Direction,
375 channel: usize,
376 frequency: f64,
377 args: Args,
378 ) -> Result<(), Error>;
379 fn frequency_components(
381 &self,
382 direction: Direction,
383 channel: usize,
384 ) -> Result<Vec<String>, Error>;
385 fn component_frequency_range(
387 &self,
388 direction: Direction,
389 channel: usize,
390 name: &str,
391 ) -> Result<Range, Error>;
392 fn component_frequency(
394 &self,
395 direction: Direction,
396 channel: usize,
397 name: &str,
398 ) -> Result<f64, Error>;
399 fn set_component_frequency(
401 &self,
402 direction: Direction,
403 channel: usize,
404 name: &str,
405 frequency: f64,
406 ) -> Result<(), Error>;
407}
408
409pub trait SampleRateControl {
411 fn sample_rate(&self, direction: Direction, channel: usize) -> Result<f64, Error>;
413 fn set_sample_rate(&self, direction: Direction, channel: usize, rate: f64)
415 -> Result<(), Error>;
416 fn get_sample_rate_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
418}
419
420pub trait BandwidthControl {
422 fn bandwidth(&self, direction: Direction, channel: usize) -> Result<f64, Error>;
424 fn set_bandwidth(&self, direction: Direction, channel: usize, bw: f64) -> Result<(), Error>;
426 fn get_bandwidth_range(&self, direction: Direction, channel: usize) -> Result<Range, Error>;
428}
429
430pub trait DcOffsetControl {
432 fn dc_offset_available(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
434 fn dc_offset_enabled(&self, direction: Direction, channel: usize) -> Result<bool, Error>;
436 fn set_dc_offset_enabled(
438 &self,
439 direction: Direction,
440 channel: usize,
441 enabled: bool,
442 ) -> Result<(), Error>;
443}
444
445pub 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 pub fn id(&self) -> usize {
458 self.channel
459 }
460
461 pub fn index(&self) -> usize {
463 self.channel
464 }
465}
466
467pub 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 pub fn id(&self) -> usize {
480 self.channel
481 }
482
483 pub fn index(&self) -> usize {
485 self.channel
486 }
487}
488
489pub 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 pub fn ports(&self) -> Result<Vec<String>, Error> {
510 self.dev.antennas(self.direction, self.channel)
511 }
512
513 pub fn selected(&self) -> Result<String, Error> {
515 self.dev.antenna(self.direction, self.channel)
516 }
517
518 pub fn select(&self, name: &str) -> Result<(), Error> {
520 self.dev.set_antenna(self.direction, self.channel, name)
521 }
522}
523
524pub 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 pub fn enabled(&self) -> Result<bool, Error> {
553 self.ensure_available()?;
554 self.dev.agc_enabled(self.direction, self.channel)
555 }
556
557 pub fn enable(&self) -> Result<(), Error> {
559 self.set_enabled(true)
560 }
561
562 pub fn disable(&self) -> Result<(), Error> {
564 self.set_enabled(false)
565 }
566
567 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
575pub 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 pub fn elements(&self) -> Result<Vec<String>, Error> {
596 self.dev.gain_elements(self.direction, self.channel)
597 }
598
599 pub fn value(&self) -> Result<Option<f64>, Error> {
601 self.dev.gain(self.direction, self.channel)
602 }
603
604 pub fn set(&self, gain: f64) -> Result<(), Error> {
606 self.dev.set_gain(self.direction, self.channel, gain)
607 }
608
609 pub fn range(&self) -> Result<Range, Error> {
611 self.dev.gain_range(self.direction, self.channel)
612 }
613
614 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
625pub 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 pub fn value(&self) -> Result<Option<f64>, Error> {
639 self.dev
640 .gain_element(self.direction, self.channel, &self.name)
641 }
642
643 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 pub fn range(&self) -> Result<Range, Error> {
651 self.dev
652 .gain_element_range(self.direction, self.channel, &self.name)
653 }
654}
655
656pub 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 pub fn value(&self) -> Result<f64, Error> {
677 self.dev.frequency(self.direction, self.channel)
678 }
679
680 pub fn set(&self, frequency: f64) -> Result<(), Error> {
682 self.set_with_args(frequency, Args::new())
683 }
684
685 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 pub fn range(&self) -> Result<Range, Error> {
693 self.dev.frequency_range(self.direction, self.channel)
694 }
695
696 pub fn components(&self) -> Result<Vec<String>, Error> {
698 self.dev.frequency_components(self.direction, self.channel)
699 }
700
701 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
712pub 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 pub fn value(&self) -> Result<f64, Error> {
726 self.dev
727 .component_frequency(self.direction, self.channel, &self.name)
728 }
729
730 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 pub fn range(&self) -> Result<Range, Error> {
738 self.dev
739 .component_frequency_range(self.direction, self.channel, &self.name)
740 }
741}
742
743pub 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 pub fn value(&self) -> Result<f64, Error> {
764 self.dev.sample_rate(self.direction, self.channel)
765 }
766
767 pub fn set(&self, rate: f64) -> Result<(), Error> {
769 self.dev.set_sample_rate(self.direction, self.channel, rate)
770 }
771
772 pub fn range(&self) -> Result<Range, Error> {
774 self.dev.get_sample_rate_range(self.direction, self.channel)
775 }
776}
777
778pub 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 pub fn value(&self) -> Result<f64, Error> {
799 self.dev.bandwidth(self.direction, self.channel)
800 }
801
802 pub fn set(&self, bandwidth: f64) -> Result<(), Error> {
804 self.dev
805 .set_bandwidth(self.direction, self.channel, bandwidth)
806 }
807
808 pub fn range(&self) -> Result<Range, Error> {
810 self.dev.get_bandwidth_range(self.direction, self.channel)
811 }
812}
813
814pub 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 pub fn enabled(&self) -> Result<bool, Error> {
843 self.ensure_available()?;
844 self.dev.dc_offset_enabled(self.direction, self.channel)
845 }
846
847 pub fn enable(&self) -> Result<(), Error> {
849 self.set_enabled(true)
850 }
851
852 pub fn disable(&self) -> Result<(), Error> {
854 self.set_enabled(false)
855 }
856
857 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#[derive(Clone)]
870pub struct Device<T> {
871 dev: T,
872}
873
874impl<T> Device<T> {
875 pub fn from_impl(dev: T) -> Self {
877 Self { dev }
878 }
879
880 pub fn as_inner(&self) -> &T {
882 &self.dev
883 }
884
885 pub fn as_inner_mut(&mut self) -> &mut T {
887 &mut self.dev
888 }
889
890 pub fn into_inner(self) -> T {
892 self.dev
893 }
894}
895
896impl<T> Device<T>
897where
898 T: TypedDeviceBackend,
899{
900 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 pub fn erase(self) -> DynDevice {
925 DynDevice::from_impl(self.dev)
926 }
927}
928
929impl<T: DeviceInfo> Device<T> {
930 pub fn driver(&self) -> Driver {
932 self.dev.driver()
933 }
934
935 pub fn id(&self) -> Result<String, Error> {
937 self.dev.id()
938 }
939
940 pub fn info(&self) -> Result<Args, Error> {
942 self.dev.info()
943 }
944
945 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 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 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 pub fn from_args<A: TryInto<Args>>(args: A) -> Result<Self, Error> {
973 Registry::default().open_args(args)
974 }
975
976 pub fn from_impl<T: DynDeviceBackend + 'static>(dev: T) -> Self {
978 Self {
979 inner: Arc::new(dev),
980 }
981 }
982
983 pub fn as_backend(&self) -> &dyn DynDeviceBackend {
985 self.inner.as_ref()
986 }
987
988 pub fn downcast_ref<D: DeviceInfo + 'static>(&self) -> Option<&D> {
990 self.inner.as_any().downcast_ref::<D>()
991 }
992
993 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 pub fn driver(&self) -> Driver {
1002 self.inner.driver()
1003 }
1004
1005 pub fn id(&self) -> Result<String, Error> {
1007 self.inner.id()
1008 }
1009
1010 pub fn info(&self) -> Result<Args, Error> {
1012 self.inner.info()
1013 }
1014
1015 pub fn capabilities(&self) -> Result<DeviceCapabilities, Error> {
1017 self.inner.capabilities()
1018 }
1019
1020 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 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 pub fn rx_streamer(&self, channels: &[usize]) -> Result<DynRxStreamer, Error> {
1034 self.rx_streamer_with_args(channels, Args::new())
1035 }
1036
1037 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 pub fn tx_streamer(&self, channels: &[usize]) -> Result<DynTxStreamer, Error> {
1056 self.tx_streamer_with_args(channels, Args::new())
1057 }
1058
1059 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 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 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 pub fn rx_streamer(&self, channels: &[usize]) -> Result<T::RxStreamer, Error> {
1470 self.rx_streamer_with_args(channels, Args::new())
1471 }
1472
1473 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 pub fn tx_streamer(&self, channels: &[usize]) -> Result<T::TxStreamer, Error> {
1489 self.tx_streamer_with_args(channels, Args::new())
1490 }
1491
1492 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 pub fn streamer(&self) -> Result<T::RxStreamer, Error> {
1508 self.streamer_with_args(Args::new())
1509 }
1510
1511 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 pub fn streamer(&self) -> Result<T::TxStreamer, Error> {
1520 self.streamer_with_args(Args::new())
1521 }
1522
1523 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 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 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 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 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 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 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 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 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 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}