From 67bf3ddadb47d3fc1b21e04965e170a72bcf9270 Mon Sep 17 00:00:00 2001 From: rhetenor Date: Wed, 26 Aug 2026 19:56:29 +0000 Subject: [PATCH] implement card storing --- src/card/decoder.rs | 6 ++-- src/card/model.rs | 6 ++-- src/storage/cardstore.rs | 63 +++++++++++++++++++++++++++++++--------- src/storage/store.rs | 4 +++ 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/card/decoder.rs b/src/card/decoder.rs index 0d2f401..b99b23d 100644 --- a/src/card/decoder.rs +++ b/src/card/decoder.rs @@ -1,14 +1,14 @@ use core::fmt::Display; -use crate::card::model::NfcPayload; +use crate::card::model::RawCard; use alloc::string::{String, ToString}; -pub fn split_nfc_hex(payload: &[u8]) -> Option { +pub fn split_nfc_hex(payload: &[u8]) -> Option { if payload.len() < 0x35A { return None; } - Some(NfcPayload { + Some(RawCard { event_encoding: payload[0..2].try_into().ok()?, card_type: payload[2], card_uuid: payload[3..5].try_into().ok()?, diff --git a/src/card/model.rs b/src/card/model.rs index 6374e64..847166d 100644 --- a/src/card/model.rs +++ b/src/card/model.rs @@ -10,7 +10,7 @@ use binary_serde::BinarySerde; #[derive(Debug, BinarySerde, PartialEq, Eq, Clone, Copy)] #[repr(C)] -pub struct NfcPayload { +pub struct RawCard { pub event_encoding: [u8; 2], pub card_type: u8, pub card_uuid: [u8; 2], @@ -238,10 +238,10 @@ pub struct Card { pub sprite: Sprite, } -impl<'a> TryFrom for Card { +impl<'a> TryFrom for Card { type Error = &'static str; - fn try_from(payload: NfcPayload) -> Result { + fn try_from(payload: RawCard) -> Result { let uuid: String = "empty for now".into(); //str::from_utf8(payload.card_uuid).unwrap().into(); let event = decode_known_event(&payload.event_encoding); let cardtype = CardType::from(payload.card_type); diff --git a/src/storage/cardstore.rs b/src/storage/cardstore.rs index 8996d2b..7b65372 100644 --- a/src/storage/cardstore.rs +++ b/src/storage/cardstore.rs @@ -3,9 +3,9 @@ use alloc::vec::Vec; use binary_serde::{BinarySerde, Endianness, DeserializeError}; -//use crate::card::model::NfcPayload; +//use crate::card::model::Nfcraw_card; -use crate::card::model::NfcPayload; +use crate::card::model::RawCard; use crate::storage::store::{Store, StoreError}; use crate::storage::{MemoryRegion,CARDSTORE_REGION}; @@ -14,16 +14,20 @@ const MAX_CARDS: usize = 20000; const COUNT_REGION: MemoryRegion = MemoryRegion { offset: CARDSTORE_REGION.offset, size: size_of::()}; -#[derive(Debug, BinarySerde, Default, PartialEq, Eq)] +#[derive(Debug, BinarySerde, PartialEq, Eq, Clone)] #[repr(C)] pub struct AllocationTableEntry { uuid: u32, + // this is the numeric offset of the AllocationTableEntry + // as well as the card entry in flash memory + // size_of::() * offset + // size_of::() * offset offset: u32, creation_date: u64, last_read_date: u64, - // how often a card has been read + // how often a card has been read by nfc read_count: u32, deleted: bool, @@ -31,9 +35,16 @@ pub struct AllocationTableEntry { reserved: [u64; 4], } -const ALLOCATION_TABLE_SIZE: usize = size_of::(); +impl AllocationTableEntry { + fn new(uuid: u32, offset: u32, timestamp: u64) -> Self { + Self { + uuid, offset, creation_date: timestamp, last_read_date: timestamp, read_count: 0, deleted: true, reserved: [0; 4] + } + } +} -const ALLOCATION_TABLE_REGION: MemoryRegion = MemoryRegion {offset: COUNT_REGION.end() as u32, size: MAX_CARDS * size_of::()}; + +const ALLOCATION_TABLE_REGION: MemoryRegion = MemoryRegion {offset: COUNT_REGION.end() as u32, size: MAX_CARDS * AllocationTableEntry::SERIALIZED_SIZE}; const CARDS_REGION: MemoryRegion = MemoryRegion { offset: ALLOCATION_TABLE_REGION.end() as u32, size: CARDSTORE_REGION.size - ALLOCATION_TABLE_REGION.end()}; @@ -58,7 +69,7 @@ impl From for CardStoreError { pub struct CardStore { store: Store, - count: usize, + count: u32, pub allocation_table: BTreeMap } @@ -68,14 +79,14 @@ impl CardStore { store.read(COUNT_REGION.offset, &mut count_bytes)?; - let count: usize = usize::from_ne_bytes(count_bytes); + let count: u32 = u32::from_ne_bytes(count_bytes); - let mut allocation_table_entries: Vec = Vec::with_capacity(ALLOCATION_TABLE_SIZE * count); + let mut allocation_table_entries: Vec = Vec::with_capacity(AllocationTableEntry::SERIALIZED_SIZE * count as usize); store .read(ALLOCATION_TABLE_REGION.offset, &mut allocation_table_entries)?; - let chunks = allocation_table_entries.into_chunks::(); + let chunks = allocation_table_entries.into_chunks::<{ AllocationTableEntry::SERIALIZED_SIZE }>(); let mut allocation_table = BTreeMap::::new(); for chunk in chunks { @@ -86,13 +97,37 @@ impl CardStore { Ok(Self { store, count, allocation_table }) } - pub fn get_card_by_uuid(&mut self, uuid: u32) -> Result { + pub fn get_card_by_uuid(&mut self, uuid: u32) -> Result { let entry = self.allocation_table.get(&uuid).ok_or(CardStoreError::NoEntry)?; - let mut payload: [u8; size_of::()] = [0; size_of::()]; - self.store.read(entry.offset, &mut payload)?; + let mut raw_card: [u8; size_of::()] = [0; size_of::()]; + self.store.read(entry.offset, &mut raw_card)?; - Ok(NfcPayload::binary_deserialize(payload.as_ref(), Endianness::Little)?) + Ok(RawCard::binary_deserialize(raw_card.as_ref(), Endianness::Little)?) } + pub fn save_raw_card(&mut self, raw_card: RawCard, timestamp: u64) -> Result<(), CardStoreError> { + + let uuid: u32 = (u16::from_ne_bytes(raw_card.event_encoding) as u32) << 16 | (u16::from_ne_bytes(raw_card.card_uuid) as u32); + let entry = match self.allocation_table.values_mut().find(|entry| entry.deleted) { + Some(entry) => entry, + None => { + let entry = AllocationTableEntry::new(uuid, self.count + 1, timestamp); + self.allocation_table.insert(uuid, entry); + self.allocation_table.get_mut(&uuid).expect("entry was just inserted") + } + }; + entry.deleted = false; + + let mut serialized_card: [u8; RawCard::SERIALIZED_SIZE] = [0; RawCard::SERIALIZED_SIZE]; + raw_card.binary_serialize(&mut serialized_card, Endianness::Little); + self.store.write(CARDS_REGION.offset + entry.offset * RawCard::SERIALIZED_SIZE as u32, &mut serialized_card)?; + + let mut serialized_entry: [u8; AllocationTableEntry::SERIALIZED_SIZE] = [0; AllocationTableEntry::SERIALIZED_SIZE]; + entry.binary_serialize(&mut serialized_entry, Endianness::Little); + self.store.write(ALLOCATION_TABLE_REGION.offset + entry.offset * AllocationTableEntry::SERIALIZED_SIZE as u32, &mut serialized_entry)?; + + self.count += 1; + Ok(()) + } } diff --git a/src/storage/store.rs b/src/storage/store.rs index 31c80e2..fdd0a02 100644 --- a/src/storage/store.rs +++ b/src/storage/store.rs @@ -37,4 +37,8 @@ impl Store { pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), StoreError> { self.storage.read(FLASH_ADDR + offset, bytes) } + + pub fn write(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), StoreError> { + self.storage.write(FLASH_ADDR + offset, bytes) + } }