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
//! Implement CDC(Communications) device
use super::*;
/// A handler of a CDC ACM(Abstract Control Model)
#[derive(Clone, Debug)]
pub struct UsbCdcAcmHandler {
pub tx_buffer: Vec<u8>,
}
impl Default for UsbCdcAcmHandler {
fn default() -> Self {
Self::new()
}
}
/// Sub class code for CDC ACM
pub const CDC_ACM_SUBCLASS: u8 = 0x02;
impl UsbCdcAcmHandler {
pub fn new() -> Self {
Self { tx_buffer: vec![] }
}
pub fn endpoints() -> Vec<UsbEndpoint> {
vec![
// state notification
UsbEndpoint {
address: 0x81, // IN
attributes: EndpointAttributes::Interrupt as u8, // Interrupt
max_packet_size: 0x08, // 8 bytes
interval: 10,
},
// bulk in
UsbEndpoint {
address: 0x82, // IN
attributes: EndpointAttributes::Bulk as u8, // Bulk
max_packet_size: 512, // 512 bytes
interval: 0,
},
// bulk out
UsbEndpoint {
address: 0x02, // OUT
attributes: EndpointAttributes::Bulk as u8, // Bulk
max_packet_size: 512, // 512 bytes
interval: 0,
},
]
}
}
impl UsbInterfaceHandler for UsbCdcAcmHandler {
fn handle_urb(
&mut self,
_interface: &UsbInterface,
ep: UsbEndpoint,
_transfer_buffer_length: u32,
_setup: SetupPacket,
req: &[u8],
) -> Result<Vec<u8>> {
if ep.attributes == EndpointAttributes::Interrupt as u8 {
// interrupt
if let Direction::In = ep.direction() {
// interrupt in
return Ok(vec![]);
}
} else {
// bulk
if let Direction::Out = ep.direction() {
// bulk out
info!(
"Got bulk out: {:?} \"{}\"",
req,
String::from_utf8_lossy(req)
);
return Ok(vec![]);
} else {
// bulk in
// Handle max packet size - return data in chunks of max_packet_size
let max_packet_size = ep.max_packet_size as usize;
let resp = if self.tx_buffer.len() > max_packet_size {
// Return only the first chunk (max_packet_size bytes)
self.tx_buffer.drain(..max_packet_size).collect::<Vec<_>>()
} else {
// Return all data if it fits in one packet
let resp = self.tx_buffer.clone();
self.tx_buffer.clear();
resp
};
return Ok(resp);
}
}
Ok(vec![])
}
fn get_class_specific_descriptor(&self) -> Vec<u8> {
vec![
// Header
0x05, // bFunctionLength
0x24, // CS_INTERFACE
0x00, // Header
0x10, 0x01, // CDC 1.2
// ACM
0x04, // bFunctionLength
0x24, // CS_INTERFACE
0x02, // ACM
0x00, // Capabilities
]
}
fn as_any(&mut self) -> &mut dyn Any {
self
}
}
#[cfg(test)]
mod tests {
use crate::util::tests::*;
use super::*;
#[test]
fn desc_verify() {
setup_test_logger();
let handler = UsbCdcAcmHandler::new();
verify_descriptor(&handler.get_class_specific_descriptor());
}
}