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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
use usb_device::class_prelude::*;
use usb_device::Result;
use crate::descriptor::AsInputReport;
extern crate ssmarshal;
use ssmarshal::serialize;
const USB_CLASS_HID: u8 = 0x03;
const USB_SUBCLASS_NONE: u8 = 0x00;
const USB_PROTOCOL_NONE: u8 = 0x00;
const HID_DESC_DESCTYPE_HID: u8 = 0x21;
const HID_DESC_DESCTYPE_HID_REPORT: u8 = 0x22;
const HID_DESC_SPEC_1_10: [u8; 2] = [0x10, 0x01];
const HID_DESC_COUNTRY_UNSPEC: u8 = 0x00;
const HID_REQ_SET_IDLE: u8 = 0x0a;
const HID_REQ_GET_IDLE: u8 = 0x02;
const HID_REQ_GET_REPORT: u8 = 0x01;
const HID_REQ_SET_REPORT: u8 = 0x09;
pub struct HIDClass<'a, B: UsbBus> {
if_num: InterfaceNumber,
out_ep: EndpointOut<'a, B>,
in_ep: EndpointIn<'a, B>,
report_descriptor: &'static [u8],
}
impl<B: UsbBus> HIDClass<'_, B> {
pub fn new<'a>(alloc: &'a UsbBusAllocator<B>, report_descriptor: &'static [u8], poll_ms: u8) -> HIDClass<'a, B> {
HIDClass {
if_num: alloc.interface(),
out_ep: alloc.interrupt(64, poll_ms),
in_ep: alloc.interrupt(64, poll_ms),
report_descriptor: report_descriptor,
}
}
pub fn push_input<IR: AsInputReport>(&self, r: &IR) -> Result<usize> {
let mut buff: [u8; 64] = [0; 64];
let size = match serialize(&mut buff, r) {
Ok(l) => l,
Err(_) => return Err(UsbError::BufferOverflow),
};
self.in_ep.write(&buff[0..size])
}
pub fn push_raw_input(&self, data: &[u8]) -> Result<usize> {
self.in_ep.write(data)
}
pub fn pull_raw_output(&self, data: &mut [u8]) -> Result<usize> {
self.out_ep.read(data)
}
}
impl<B: UsbBus> UsbClass<B> for HIDClass<'_, B> {
fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
writer.interface(
self.if_num,
USB_CLASS_HID,
USB_SUBCLASS_NONE,
USB_PROTOCOL_NONE)?;
writer.write(
HID_DESC_DESCTYPE_HID,
&[
HID_DESC_SPEC_1_10[0], HID_DESC_SPEC_1_10[1],
HID_DESC_COUNTRY_UNSPEC,
1,
HID_DESC_DESCTYPE_HID_REPORT,
(self.report_descriptor.len() & 0xFF) as u8, (self.report_descriptor.len()>>8 & 0xFF) as u8,
])?;
writer.endpoint(&self.out_ep)?;
writer.endpoint(&self.in_ep)?;
Ok(())
}
fn control_in(&mut self, xfer: ControlIn<B>) {
let req = xfer.request();
if req.index != u8::from(self.if_num) as u16 {
return;
}
match (req.request_type, req.request) {
(control::RequestType::Standard, control::Request::GET_DESCRIPTOR) => {
match (req.value>>8) as u8 {
HID_DESC_DESCTYPE_HID_REPORT => {
xfer.accept_with_static(self.report_descriptor).ok();
},
HID_DESC_DESCTYPE_HID => {
let buf = &[
9,
HID_DESC_DESCTYPE_HID,
HID_DESC_SPEC_1_10[0], HID_DESC_SPEC_1_10[1],
HID_DESC_COUNTRY_UNSPEC,
1,
HID_DESC_DESCTYPE_HID_REPORT,
(self.report_descriptor.len() & 0xFF) as u8, (self.report_descriptor.len()>>8 & 0xFF) as u8,
];
xfer.accept_with(buf).ok();
},
_ => {},
}
},
(control::RequestType::Class, HID_REQ_GET_REPORT) => {
xfer.reject().ok();
},
(control::RequestType::Class, HID_REQ_GET_IDLE) => {
xfer.reject().ok();
},
_ => {},
}
}
fn control_out(&mut self, xfer: ControlOut<B>) {
let req = xfer.request();
if !(req.recipient == control::Recipient::Interface && req.index == u8::from(self.if_num) as u16) {
return;
}
match req.request {
HID_REQ_SET_IDLE => {
xfer.accept().ok();
},
HID_REQ_SET_REPORT => {
xfer.reject().ok();
},
_ => { xfer.reject().ok(); }
}
}
}