ledger_lib/transport/
mod.rs1use std::{fmt::Debug, time::Duration};
16
17use tracing::{debug, warn};
18
19#[cfg(feature = "transport_usb")]
20mod usb;
21#[cfg(feature = "transport_usb")]
22pub use usb::{UsbDevice, UsbInfo, UsbTransport};
23
24#[cfg(feature = "transport_ble")]
25mod ble;
26#[cfg(feature = "transport_ble")]
27pub use ble::{BleDevice, BleInfo, BleTransport};
28
29#[cfg(feature = "transport_tcp")]
30mod tcp;
31#[cfg(feature = "transport_tcp")]
32pub use tcp::{TcpDevice, TcpInfo, TcpTransport};
33
34use crate::{
35 info::{ConnInfo, LedgerInfo},
36 Error, Exchange, Filters,
37};
38
39#[cfg_attr(not(feature = "unstable_async_trait"), async_trait::async_trait)]
41pub trait Transport {
42 type Filters: Debug;
44 type Info: Debug;
46 type Device: Exchange;
48
49 async fn list(&mut self, filters: Self::Filters) -> Result<Vec<LedgerInfo>, Error>;
51
52 async fn connect(&mut self, info: Self::Info) -> Result<Self::Device, Error>;
54}
55
56pub struct GenericTransport {
59 #[cfg(feature = "transport_usb")]
60 usb: UsbTransport,
61
62 #[cfg(feature = "transport_ble")]
63 ble: BleTransport,
64
65 #[cfg(feature = "transport_tcp")]
66 tcp: TcpTransport,
67}
68
69pub enum GenericDevice {
72 #[cfg(feature = "transport_usb")]
73 Usb(UsbDevice),
74
75 #[cfg(feature = "transport_ble")]
76 Ble(BleDevice),
77
78 #[cfg(feature = "transport_tcp")]
79 Tcp(TcpDevice),
80}
81
82impl GenericTransport {
83 pub async fn new() -> Result<Self, Error> {
85 debug!("Initialising GenericTransport");
86
87 Ok(Self {
88 #[cfg(feature = "transport_usb")]
89 usb: UsbTransport::new()?,
90
91 #[cfg(feature = "transport_ble")]
92 ble: BleTransport::new().await?,
93
94 #[cfg(feature = "transport_tcp")]
95 tcp: TcpTransport::new()?,
96 })
97 }
98}
99
100#[cfg_attr(not(feature = "unstable_async_trait"), async_trait::async_trait)]
101impl Transport for GenericTransport {
102 type Filters = Filters;
103 type Info = LedgerInfo;
104 type Device = GenericDevice;
105
106 async fn list(&mut self, filters: Filters) -> Result<Vec<LedgerInfo>, Error> {
108 let mut devices = vec![];
109
110 #[cfg(feature = "transport_usb")]
111 if filters == Filters::Any || filters == Filters::Hid {
112 let mut d = self.usb.list(()).await?;
113 devices.append(&mut d);
114 }
115
116 #[cfg(feature = "transport_ble")]
117 if filters == Filters::Any || filters == Filters::Ble {
118 match self.ble.list(()).await {
123 Ok(mut d) => devices.append(&mut d),
124 Err(e) if filters == Filters::Any => {
125 warn!("BLE discovery failed: {e:?}");
126 }
127 Err(e) => return Err(e),
128 }
129 }
130
131 #[cfg(feature = "transport_tcp")]
132 if filters == Filters::Any || filters == Filters::Tcp {
133 let mut d = self.tcp.list(()).await?;
134 devices.append(&mut d);
135 }
136
137 Ok(devices)
138 }
139
140 async fn connect(&mut self, info: LedgerInfo) -> Result<GenericDevice, Error> {
143 debug!("Connecting to device: {:?}", info);
144
145 let d = match info.conn {
146 #[cfg(feature = "transport_usb")]
147 ConnInfo::Usb(i) => self.usb.connect(i).await.map(GenericDevice::Usb)?,
148 #[cfg(feature = "transport_tcp")]
149 ConnInfo::Tcp(i) => self.tcp.connect(i).await.map(GenericDevice::Tcp)?,
150 #[cfg(feature = "transport_ble")]
151 ConnInfo::Ble(i) => self.ble.connect(i).await.map(GenericDevice::Ble)?,
152 };
153
154 Ok(d)
155 }
156}
157
158impl GenericDevice {
159 pub fn info(&self) -> ConnInfo {
161 match self {
162 GenericDevice::Usb(d) => d.info.clone().into(),
163 GenericDevice::Ble(d) => d.info.clone().into(),
164 GenericDevice::Tcp(d) => d.info.clone().into(),
165 }
166 }
167
168 pub(crate) async fn is_connected(&self) -> Result<bool, Error> {
169 match self {
170 GenericDevice::Usb(d) => d.is_connected().await,
171 GenericDevice::Ble(d) => d.is_connected().await,
172 GenericDevice::Tcp(d) => d.is_connected().await,
173 }
174 }
175}
176
177#[cfg_attr(not(feature = "unstable_async_trait"), async_trait::async_trait)]
178impl Exchange for GenericDevice {
179 async fn exchange(&mut self, command: &[u8], timeout: Duration) -> Result<Vec<u8>, Error> {
181 match self {
182 #[cfg(feature = "transport_usb")]
183 Self::Usb(d) => d.exchange(command, timeout).await,
184 Self::Ble(d) => d.exchange(command, timeout).await,
185 Self::Tcp(d) => d.exchange(command, timeout).await,
186 }
187 }
188}
189
190#[cfg(feature = "transport_usb")]
191impl From<UsbDevice> for GenericDevice {
192 fn from(value: UsbDevice) -> Self {
193 Self::Usb(value)
194 }
195}
196
197#[cfg(feature = "transport_tcp")]
198impl From<TcpDevice> for GenericDevice {
199 fn from(value: TcpDevice) -> Self {
200 Self::Tcp(value)
201 }
202}
203
204#[cfg(feature = "transport_ble")]
205impl From<BleDevice> for GenericDevice {
206 fn from(value: BleDevice) -> Self {
207 Self::Ble(value)
208 }
209}