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