ctaphid_app/
command.rs

1#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2pub enum Command {
3    // mandatory for CTAP1
4    Ping,
5    Msg,
6    Init,
7    Error,
8
9    // optional
10    Wink,
11    Lock,
12
13    // mandatory for CTAP2
14    Cbor,
15    Cancel,
16    KeepAlive,
17
18    // ISO7816 only commands
19    Deselect,
20
21    // vendor-assigned range from 0x40 to 0x7f
22    Vendor(VendorCommand),
23}
24
25impl Command {
26    pub fn into_u8(self) -> u8 {
27        self.into()
28    }
29}
30
31impl TryFrom<u8> for Command {
32    type Error = ();
33
34    fn try_from(from: u8) -> core::result::Result<Command, ()> {
35        match from {
36            0x01 => Ok(Command::Ping),
37            0x03 => Ok(Command::Msg),
38            0x06 => Ok(Command::Init),
39            0x3f => Ok(Command::Error),
40            0x08 => Ok(Command::Wink),
41            0x04 => Ok(Command::Lock),
42            0x10 => Ok(Command::Cbor),
43            0x11 => Ok(Command::Cancel),
44            0x12 => Ok(Command::Deselect),
45            0x3b => Ok(Command::KeepAlive),
46            code => Ok(Command::Vendor(VendorCommand::try_from(code)?)),
47        }
48    }
49}
50
51/// Vendor CTAPHID commands, from 0x40 to 0x7f.
52#[repr(u8)]
53#[derive(Copy, Clone, Debug, Eq, PartialEq)]
54pub enum VendorCommand {
55    H40 = 0x40,
56    H41 = 0x41,
57    H42 = 0x42,
58    H43 = 0x43,
59    H44 = 0x44,
60    H45 = 0x45,
61    H46 = 0x46,
62    H47 = 0x47,
63    H48 = 0x48,
64    H49 = 0x49,
65    H4A = 0x4A,
66    H4B = 0x4B,
67    H4C = 0x4C,
68    H4D = 0x4D,
69    H4E = 0x4E,
70    H4F = 0x4F,
71    H50 = 0x50,
72    H51 = 0x51,
73    H52 = 0x52,
74    H53 = 0x53,
75    H54 = 0x54,
76    H55 = 0x55,
77    H56 = 0x56,
78    H57 = 0x57,
79    H58 = 0x58,
80    H59 = 0x59,
81    H5A = 0x5A,
82    H5B = 0x5B,
83    H5C = 0x5C,
84    H5D = 0x5D,
85    H5E = 0x5E,
86    H5F = 0x5F,
87    H60 = 0x60,
88    H61 = 0x61,
89    H62 = 0x62,
90    H63 = 0x63,
91    H64 = 0x64,
92    H65 = 0x65,
93    H66 = 0x66,
94    H67 = 0x67,
95    H68 = 0x68,
96    H69 = 0x69,
97    H6A = 0x6A,
98    H6B = 0x6B,
99    H6C = 0x6C,
100    H6D = 0x6D,
101    H6E = 0x6E,
102    H6F = 0x6F,
103    H70 = 0x70,
104    H71 = 0x71,
105    H72 = 0x72,
106    H73 = 0x73,
107    H74 = 0x74,
108    H75 = 0x75,
109    H76 = 0x76,
110    H77 = 0x77,
111    H78 = 0x78,
112    H79 = 0x79,
113    H7A = 0x7A,
114    H7B = 0x7B,
115    H7C = 0x7C,
116    H7D = 0x7D,
117    H7E = 0x7E,
118    H7F = 0x7F,
119}
120
121impl VendorCommand {
122    pub const FIRST: u8 = 0x40;
123    pub const LAST: u8 = 0x7f;
124}
125
126impl TryFrom<u8> for VendorCommand {
127    type Error = ();
128
129    fn try_from(from: u8) -> core::result::Result<Self, ()> {
130        if (Self::FIRST..=Self::LAST).contains(&from) {
131            Ok(unsafe { core::mem::transmute::<u8, VendorCommand>(from) })
132        } else {
133            Err(())
134        }
135    }
136}
137
138impl From<Command> for u8 {
139    fn from(command: Command) -> u8 {
140        use Command::*;
141        match command {
142            Ping => 0x01,
143            Msg => 0x03,
144            Init => 0x06,
145            Error => 0x3f,
146            Wink => 0x08,
147            Lock => 0x04,
148            Cbor => 0x10,
149            Cancel => 0x11,
150            Deselect => 0x12,
151            KeepAlive => 0x3b,
152            Vendor(command) => command as u8,
153        }
154    }
155}