1use crate::{Error, Result};
2use bitfield::bitfield;
3use std::{fmt, str::FromStr};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum Zone {
7 Data,
8 Config,
9}
10
11impl FromStr for Zone {
12 type Err = Error;
13
14 fn from_str(s: &str) -> Result<Self> {
15 match s.to_lowercase().as_str() {
16 "data" => Ok(Self::Data),
17 "config" => Ok(Self::Config),
18 _ => Err(Error::invalid_address()),
19 }
20 }
21}
22
23impl fmt::Display for Zone {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 match self {
26 Self::Config => f.write_str("config"),
27 Self::Data => f.write_str("data"),
28 }
29 }
30}
31
32#[derive(Debug, PartialEq, Eq, Clone, Copy)]
33pub enum DataBuffer {
34 TempKey,
35 MessageDigest,
36 AlternateKey,
37}
38
39impl From<&DataBuffer> for u8 {
40 fn from(v: &DataBuffer) -> Self {
41 match v {
42 DataBuffer::TempKey => 0,
43 DataBuffer::MessageDigest => 1,
44 DataBuffer::AlternateKey => 2,
45 }
46 }
47}
48
49impl From<u8> for DataBuffer {
50 fn from(v: u8) -> Self {
51 match v & 3 {
52 0 => Self::TempKey,
53 1 => Self::MessageDigest,
54 2 => Self::AlternateKey,
55 _ => unreachable!(),
56 }
57 }
58}
59
60#[derive(Debug, PartialEq, Eq, Clone, Copy)]
61pub enum Address {
62 Otp(OffsetAddress),
63 Config(OffsetAddress),
64 Data(DataAddress),
65}
66
67bitfield! {
68 #[derive(PartialEq, Eq, Clone, Copy)]
69 pub struct OffsetAddress(u16);
70 impl Debug;
71 u8, offset, set_offset: 10, 8;
72 u8, block, set_block: 12, 11;
73}
74
75bitfield! {
76 #[derive(PartialEq, Clone, Copy, Eq)]
77 pub struct DataAddress(u16);
78 impl Debug;
79 u8, block, set_block: 3, 0;
80 u8, offset, set_offset: 10, 8;
81 u8, slot, set_slot: 14, 11;
82}
83
84impl From<&Address> for u16 {
85 fn from(v: &Address) -> Self {
86 match v {
87 Address::Otp(addr) => addr.0,
88 Address::Config(addr) => addr.0,
89 Address::Data(addr) => addr.0,
90 }
91 }
92}
93
94impl Address {
95 pub fn otp(block: u8, offset: u8) -> Result<Self> {
96 if block > 4 || offset > 7 {
97 return Err(Error::invalid_address());
98 }
99 let mut address = OffsetAddress(0);
100 address.set_block(block);
101 address.set_offset(offset);
102 Ok(Self::Otp(address))
103 }
104
105 pub fn config(block: u8, offset: u8) -> Result<Self> {
106 if block > 4 || offset > 7 {
107 return Err(Error::invalid_address());
108 }
109 let mut address = OffsetAddress(0);
110 address.set_block(block);
111 address.set_offset(offset);
112 Ok(Self::Config(address))
113 }
114
115 pub fn slot_config(slot: u8) -> Result<Self> {
116 if slot > 15 {
117 return Err(Error::invalid_address());
118 }
119 let (block, offset) = if slot <= 5 {
120 (0, (20 + slot * 2) >> 2)
121 } else {
122 (1, ((slot - 5) * 2) >> 2)
123 };
124 Self::config(block, offset)
125 }
126
127 pub fn key_config(slot: u8) -> Result<Self> {
128 if slot > 15 {
129 return Err(Error::invalid_address());
130 }
131 Self::config(3, (slot * 2) >> 2)
132 }
133
134 pub fn data(slot: u8, block: u8, offset: u8) -> Result<Self> {
135 if slot > 15
136 || (slot < 8 && block > 1)
137 || (slot == 8 && block > 15)
138 || (slot > 8 && block > 7)
139 {
140 return Err(Error::invalid_address());
141 }
142 let mut address = DataAddress(0);
143 address.set_block(block);
144 address.set_offset(offset);
145 address.set_slot(slot);
146 Ok(Self::Data(address))
147 }
148
149 pub fn zone(&self) -> u8 {
150 match self {
151 Self::Config(_) => 0x00,
152 Self::Otp(_) => 0x01,
153 Self::Data(_) => 0x02,
154 }
155 }
156}