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