ledger_lib/
info.rs

1//! Device information types and connection filters
2
3use strum::{Display, EnumString};
4
5use crate::Filters;
6
7use super::transport;
8
9/// Ledger device information
10#[derive(Clone, PartialEq, Debug)]
11pub struct LedgerInfo {
12    /// Device Model
13    pub model: Model,
14
15    /// Device connection information
16    pub conn: ConnInfo,
17}
18
19impl std::fmt::Display for LedgerInfo {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        write!(f, "{} ({})", self.model, self.conn)
22    }
23}
24
25impl LedgerInfo {
26    /// Fetch connection kind enumeration
27    pub fn kind(&self) -> ConnType {
28        match &self.conn {
29            #[cfg(feature = "transport_usb")]
30            ConnInfo::Usb(_) => ConnType::Usb,
31            #[cfg(feature = "transport_tcp")]
32            ConnInfo::Tcp(_) => ConnType::Tcp,
33            #[cfg(feature = "transport_ble")]
34            ConnInfo::Ble(_) => ConnType::Ble,
35        }
36    }
37}
38
39/// Ledger device models
40#[derive(Clone, PartialEq, Debug, Display, EnumString)]
41pub enum Model {
42    /// Nano S
43    NanoS,
44    /// Nano S Plus
45    NanoSPlus,
46    /// Nano X
47    NanoX,
48    /// Stax
49    Stax,
50    /// Unknown model
51    Unknown(u16),
52}
53
54impl Model {
55    /// Convert a USB PID to a [Model] kind
56    ///
57    /// Note that ledger PIDs vary depending on the device state so only the top byte is used
58    /// for matching.
59    pub fn from_pid(pid: u16) -> Model {
60        match pid & 0xFF00 {
61            // TODO: support all the models
62            //0x0001 => Ok(Model::NanoS),
63            0x4000 => Model::NanoX,
64            0x5000 => Model::NanoSPlus,
65            //0x0006 => Ok(Model::Stax),
66            _ => Model::Unknown(pid),
67        }
68    }
69}
70
71/// Ledger connection information
72#[derive(Clone, PartialEq, Debug)]
73pub enum ConnInfo {
74    #[cfg(feature = "transport_usb")]
75    Usb(transport::UsbInfo),
76    #[cfg(feature = "transport_tcp")]
77    Tcp(transport::TcpInfo),
78    #[cfg(feature = "transport_ble")]
79    Ble(transport::BleInfo),
80}
81
82/// Ledger connection types
83#[derive(Copy, Clone, PartialEq, Debug)]
84pub enum ConnType {
85    Usb,
86    Tcp,
87    Ble,
88}
89
90impl From<ConnType> for Filters {
91    /// Convert a connection type to a discovery filter
92    fn from(value: ConnType) -> Self {
93        match value {
94            ConnType::Usb => Filters::Hid,
95            ConnType::Tcp => Filters::Tcp,
96            ConnType::Ble => Filters::Ble,
97        }
98    }
99}
100
101impl std::fmt::Display for ConnInfo {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        match self {
104            #[cfg(feature = "transport_usb")]
105            Self::Usb(i) => write!(f, "HID {}", i),
106            #[cfg(feature = "transport_tcp")]
107            Self::Tcp(i) => write!(f, "TCP {}", i),
108            #[cfg(feature = "transport_ble")]
109            Self::Ble(i) => write!(f, "BLE {}", i),
110        }
111    }
112}
113
114#[cfg(feature = "transport_usb")]
115impl From<transport::UsbInfo> for ConnInfo {
116    fn from(value: transport::UsbInfo) -> Self {
117        Self::Usb(value)
118    }
119}
120
121#[cfg(feature = "transport_tcp")]
122impl From<transport::TcpInfo> for ConnInfo {
123    fn from(value: transport::TcpInfo) -> Self {
124        Self::Tcp(value)
125    }
126}
127
128#[cfg(feature = "transport_ble")]
129impl From<transport::BleInfo> for ConnInfo {
130    fn from(value: transport::BleInfo) -> Self {
131        Self::Ble(value)
132    }
133}
134
135/// Application info object
136#[derive(Debug, Clone, PartialEq)]
137pub struct AppInfo {
138    pub name: String,
139    pub version: String,
140    pub flags: ledger_proto::apdus::AppFlags,
141}
142
143/// Device info object
144#[derive(Debug, Clone, PartialEq)]
145pub struct DeviceInfo {
146    pub target_id: [u8; 4],
147    pub se_version: String,
148    pub mcu_version: String,
149    pub flags: Vec<u8>,
150}