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
use crate::protocol::{Command, Status};
use core::fmt::Debug;
use core::future::Future;

/// Trait for the firmware update service.
///
/// The service is responsible for establishing the connection to the firmware update
/// service and performing the request-response cycle with the update service.
pub trait UpdateService {
    /// Error type
    type Error: core::fmt::Debug;

    /// Future returned by send
    type RequestFuture<'m>: Future<Output = Result<Command<'m>, Self::Error>> + 'm
    where
        Self: 'm;

    /// Send the status to the server, and return the Command responded by the service
    /// rx buffer.
    fn request<'m>(&'m mut self, status: &'m Status<'m>) -> Self::RequestFuture<'m>;
}

/// Type representing the firmware version
#[cfg(feature = "defmt")]
pub trait FirmwareVersion: PartialEq + AsRef<[u8]> + Sized + Debug + Clone + defmt::Format {
    fn from_slice(data: &[u8]) -> Result<Self, ()>;
}

#[cfg(not(feature = "defmt"))]
pub trait FirmwareVersion: PartialEq + AsRef<[u8]> + Sized + Debug + Clone {
    fn from_slice(data: &[u8]) -> Result<Self, ()>;
}

impl<const N: usize> FirmwareVersion for heapless::Vec<u8, N> {
    fn from_slice(data: &[u8]) -> Result<Self, ()> {
        heapless::Vec::from_slice(data)
    }
}

#[cfg(feature = "std")]
mod stdlib {
    extern crate std;
    use std::vec::Vec;
    impl super::FirmwareVersion for Vec<u8> {
        fn from_slice(data: &[u8]) -> Result<Self, ()> {
            Ok(data.into())
        }
    }
}

/// The current status of the firmware on a device
pub struct FirmwareStatus<VERSION>
where
    VERSION: FirmwareVersion,
{
    /// Current firmware version
    pub current_version: VERSION,
    /// Offset written of next firmware
    pub next_offset: u32,
    /// Next version being written
    pub next_version: Option<VERSION>,
}

impl<VERSION> Clone for FirmwareStatus<VERSION>
where
    VERSION: FirmwareVersion + Clone,
{
    fn clone(&self) -> Self {
        Self {
            current_version: self.current_version.clone(),
            next_offset: self.next_offset,
            next_version: self.next_version.clone(),
        }
    }
}

pub trait FirmwareDevice {
    const MTU: usize;
    type Version: FirmwareVersion;
    type Error;

    // Future returned by status
    type StatusFuture<'m>: Future<Output = Result<FirmwareStatus<Self::Version>, Self::Error>> + 'm
    where
        Self: 'm;
    /// Return the status of the currently running firmware.
    fn status(&mut self) -> Self::StatusFuture<'_>;

    // Future returned by start
    type StartFuture<'m>: Future<Output = Result<(), Self::Error>> + 'm
    where
        Self: 'm;
    /// Prepare for starting the firmware update process.
    fn start<'m>(&'m mut self, version: &'m [u8]) -> Self::StartFuture<'m>;

    /// Future returned by write
    type WriteFuture<'m>: Future<Output = Result<(), Self::Error>> + 'm
    where
        Self: 'm;
    /// Write a block of firmware at the expected offset.
    fn write<'m>(&'m mut self, offset: u32, data: &'m [u8]) -> Self::WriteFuture<'m>;

    /// Future returned by update
    type UpdateFuture<'m>: Future<Output = Result<(), Self::Error>> + 'm
    where
        Self: 'm;
    /// Finish the firmware write and mark device to be updated
    fn update<'m>(&'m mut self, version: &'m [u8], checksum: &'m [u8]) -> Self::UpdateFuture<'m>;

    /// Future returned by synced
    type SyncedFuture<'m>: Future<Output = Result<(), Self::Error>> + 'm
    where
        Self: 'm;
    /// Mark firmware as being in sync with the expected
    fn synced(&mut self) -> Self::SyncedFuture<'_>;
}