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
use displaydoc::Display;
#[cfg(any(feature = "std", test))]
use thiserror::Error;
/// Error when reading the functional descriptor.
#[derive(Debug, Display)]
#[cfg_attr(any(feature = "std", test), derive(Error))]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub enum Error {
/// The data is too short (got: {0}, expected: 9).
DataTooShort(usize),
}
/// Functional descriptor.
#[derive(Debug, Copy, Clone)]
pub struct FunctionalDescriptor {
/// bitCanDnload.
///
/// Bit 0: download capable.
pub can_download: bool,
/// bitCanUpload.
///
/// Bit 1: upload capable.
pub can_upload: bool,
/// bitManifestationTolerant.
///
/// Bit 2: device is able to communicate via USB after Manifestation phase.
pub manifestation_tolerant: bool,
/// bitWillDetach.
///
/// Bit 3: device will perform a bus detach-attach sequence when it receives a DFU_DETACH
/// request. The host must not issue a USB Reset.
pub will_detach: bool,
/// wDetachTimeOut.
///
/// Time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request.
/// If this time elapses without a USB reset, then the device will terminate the
/// Reconfiguration phase and revert back to normal operation. This represents the maximum
/// time that the device can wait (depending on its timers, etc.). The host may specify a
/// shorter timeout in the DFU_DETACH request.
pub detach_timeout: u16,
/// wTransferSize.
///
/// Maximum number of bytes that the device can accept per control-write transaction.
pub transfer_size: u16,
/// bcdDFUVersion.
///
/// Numeric expression identifying the version of the DFU Specification release.
pub dfu_version: (u8, u8),
}
impl FunctionalDescriptor {
/// Read functional descriptor from a slice of bytes.
pub fn from_bytes(mut bytes: &[u8]) -> Option<Result<Self, Error>> {
use bytes::Buf;
let len = bytes.len();
if len < 2 {
return None;
}
bytes.advance(1);
let descriptor_type = bytes.get_u8();
if descriptor_type != 0x21 {
return None;
}
if len < 9 {
return Some(Err(Error::DataTooShort(len)));
}
let attributes = bytes.get_u8();
let can_download = attributes & (1 << 0) > 0;
let can_upload = attributes & (1 << 1) > 0;
let manifestation_tolerant = attributes & (1 << 2) > 0;
let will_detach = attributes & (1 << 3) > 0;
let detach_timeout = bytes.get_u16_le();
let transfer_size = bytes.get_u16_le();
let minor = bytes.get_u8();
let major = bytes.get_u8();
let dfu_version = (major, minor);
Some(Ok(Self {
can_download,
can_upload,
manifestation_tolerant,
will_detach,
detach_timeout,
transfer_size,
dfu_version,
}))
}
}