1use core::cmp;
10
11use super::descriptors;
12use super::descriptors::Buffer64;
13use super::descriptors::DescriptorType;
14use super::descriptors::EndpointAddress;
15use super::descriptors::EndpointDescriptor;
16use super::descriptors::HIDCountryCode;
17use super::descriptors::HIDDescriptor;
18use super::descriptors::HIDSubordinateDescriptor;
19use super::descriptors::InterfaceDescriptor;
20use super::descriptors::ReportDescriptor;
21use super::descriptors::TransferDirection;
22use super::usbc_client_ctrl::ClientCtrl;
23
24use kernel::hil;
25use kernel::hil::usb::TransferType;
26use kernel::utilities::cells::OptionalCell;
27use kernel::utilities::cells::TakeCell;
28use kernel::ErrorCode;
29
30const ENDPOINT_NUM: usize = 1;
32
33const OUT_BUFFER: usize = 0;
34const IN_BUFFER: usize = 1;
35
36static LANGUAGES: &[u16; 1] = &[
37 0x0409, ];
39pub const MAX_CTRL_PACKET_SIZE: u8 = 64;
41
42const N_ENDPOINTS: usize = 2;
43
44static REPORT_DESCRIPTOR: &[u8] = &[
50 0x06, 0xD0, 0xF1, 0x09, 0x01, 0xA1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x40, 0x91, 0x02, 0xC0, ];
67
68static REPORT: ReportDescriptor<'static> = ReportDescriptor {
69 desc: REPORT_DESCRIPTOR,
70};
71
72static SUB_HID_DESCRIPTOR: &[HIDSubordinateDescriptor] = &[HIDSubordinateDescriptor {
73 typ: DescriptorType::Report,
74 len: REPORT_DESCRIPTOR.len() as u16,
75}];
76
77static HID_DESCRIPTOR: HIDDescriptor<'static> = HIDDescriptor {
78 hid_class: 0x0110,
79 country_code: HIDCountryCode::NotSupported,
80 sub_descriptors: SUB_HID_DESCRIPTOR,
81};
82
83pub struct CtapHid<'a, U: 'a> {
85 client_ctrl: ClientCtrl<'a, 'static, U>,
87
88 buffers: [Buffer64; N_ENDPOINTS],
90
91 client: OptionalCell<&'a dyn hil::usb_hid::Client<'a, [u8; 64]>>,
92
93 send_buffer: TakeCell<'static, [u8; 64]>,
95
96 recv_buffer: TakeCell<'static, [u8; 64]>,
99}
100
101impl<'a, U: hil::usb::UsbController<'a>> CtapHid<'a, U> {
102 pub fn new(
103 controller: &'a U,
104 vendor_id: u16,
105 product_id: u16,
106 strings: &'static [&'static str; 3],
107 ) -> Self {
108 let interfaces: &mut [InterfaceDescriptor] = &mut [InterfaceDescriptor {
109 interface_number: 0,
110 interface_class: 0x03, interface_subclass: 0x00, interface_protocol: 0x00, ..InterfaceDescriptor::default()
114 }];
115
116 let endpoints: &[&[EndpointDescriptor]] = &[&[
117 EndpointDescriptor {
118 endpoint_address: EndpointAddress::new_const(
119 ENDPOINT_NUM,
120 TransferDirection::DeviceToHost,
121 ),
122 transfer_type: TransferType::Interrupt,
123 max_packet_size: 64,
124 interval: 5,
125 },
126 EndpointDescriptor {
127 endpoint_address: EndpointAddress::new_const(
128 ENDPOINT_NUM,
129 TransferDirection::HostToDevice,
130 ),
131 transfer_type: TransferType::Interrupt,
132 max_packet_size: 64,
133 interval: 5,
134 },
135 ]];
136
137 let (device_descriptor_buffer, other_descriptor_buffer) =
138 descriptors::create_descriptor_buffers(
139 descriptors::DeviceDescriptor {
140 vendor_id,
141 product_id,
142 manufacturer_string: 1,
143 product_string: 2,
144 serial_number_string: 3,
145 class: 0x03, max_packet_size_ep0: MAX_CTRL_PACKET_SIZE,
147 ..descriptors::DeviceDescriptor::default()
148 },
149 descriptors::ConfigurationDescriptor::default(),
150 interfaces,
151 endpoints,
152 Some(&HID_DESCRIPTOR),
153 None,
154 );
155
156 CtapHid {
157 client_ctrl: ClientCtrl::new(
158 controller,
159 device_descriptor_buffer,
160 other_descriptor_buffer,
161 Some(&HID_DESCRIPTOR),
162 Some(&REPORT),
163 LANGUAGES,
164 strings,
165 ),
166 buffers: [Buffer64::default(), Buffer64::default()],
167 client: OptionalCell::empty(),
168 send_buffer: TakeCell::empty(),
169 recv_buffer: TakeCell::empty(),
170 }
171 }
172
173 #[inline]
174 fn controller(&self) -> &'a U {
175 self.client_ctrl.controller()
176 }
177
178 pub fn set_client(&'a self, client: &'a dyn hil::usb_hid::Client<'a, [u8; 64]>) {
179 self.client.set(client);
180 }
181}
182
183impl<'a, U: hil::usb::UsbController<'a>> hil::usb_hid::UsbHid<'a, [u8; 64]> for CtapHid<'a, U> {
184 fn send_buffer(
185 &'a self,
186 send: &'static mut [u8; 64],
187 ) -> Result<usize, (ErrorCode, &'static mut [u8; 64])> {
188 let len = send.len();
189
190 self.send_buffer.replace(send);
191 self.controller().endpoint_resume_in(ENDPOINT_NUM);
192
193 Ok(len)
194 }
195
196 fn send_cancel(&'a self) -> Result<&'static mut [u8; 64], ErrorCode> {
197 match self.send_buffer.take() {
198 Some(buf) => Ok(buf),
199 None => Err(ErrorCode::BUSY),
200 }
201 }
202
203 fn receive_buffer(
204 &'a self,
205 recv: &'static mut [u8; 64],
206 ) -> Result<(), (ErrorCode, &'static mut [u8; 64])> {
207 self.recv_buffer.replace(recv);
208 self.controller().endpoint_resume_out(ENDPOINT_NUM);
209 Ok(())
210 }
211
212 fn receive_cancel(&'a self) -> Result<&'static mut [u8; 64], ErrorCode> {
213 match self.recv_buffer.take() {
214 Some(buf) => Ok(buf),
215 None => Err(ErrorCode::BUSY),
216 }
217 }
218}
219
220impl<'a, U: hil::usb::UsbController<'a>> hil::usb::Client<'a> for CtapHid<'a, U> {
221 fn enable(&'a self) {
222 self.client_ctrl.enable();
224
225 self.controller()
227 .endpoint_set_out_buffer(ENDPOINT_NUM, &self.buffers[OUT_BUFFER].buf);
228 self.controller()
229 .endpoint_set_in_buffer(ENDPOINT_NUM, &self.buffers[IN_BUFFER].buf);
230 self.controller()
231 .endpoint_in_out_enable(TransferType::Interrupt, ENDPOINT_NUM);
232 }
233
234 fn attach(&'a self) {
235 self.client_ctrl.attach();
236 }
237
238 fn bus_reset(&'a self) {}
239
240 fn ctrl_setup(&'a self, endpoint: usize) -> hil::usb::CtrlSetupResult {
242 self.client_ctrl.ctrl_setup(endpoint)
243 }
244
245 fn ctrl_in(&'a self, endpoint: usize) -> hil::usb::CtrlInResult {
247 self.client_ctrl.ctrl_in(endpoint)
248 }
249
250 fn ctrl_out(&'a self, endpoint: usize, packet_bytes: u32) -> hil::usb::CtrlOutResult {
252 self.client_ctrl.ctrl_out(endpoint, packet_bytes)
253 }
254
255 fn ctrl_status(&'a self, endpoint: usize) {
256 self.client_ctrl.ctrl_status(endpoint)
257 }
258
259 fn ctrl_status_complete(&'a self, endpoint: usize) {
261 if self.send_buffer.is_some() {
262 self.controller().endpoint_resume_in(ENDPOINT_NUM);
263 }
264
265 self.client_ctrl.ctrl_status_complete(endpoint)
266 }
267
268 fn packet_in(&'a self, transfer_type: TransferType, _endpoint: usize) -> hil::usb::InResult {
277 match transfer_type {
278 TransferType::Interrupt => {
279 self.send_buffer
280 .take()
281 .map_or(hil::usb::InResult::Delay, |buf| {
282 let packet = &self.buffers[IN_BUFFER].buf;
285
286 for i in 0..64 {
288 packet[i].set(buf[i]);
289 }
290
291 self.send_buffer.replace(buf);
293
294 hil::usb::InResult::Packet(64)
296 })
297 }
298 TransferType::Bulk | TransferType::Control | TransferType::Isochronous => {
299 panic!("Transfer protocol not supported by CTAP v2");
300 }
301 }
302 }
303
304 fn packet_out(
308 &'a self,
309 transfer_type: TransferType,
310 endpoint: usize,
311 packet_bytes: u32,
312 ) -> hil::usb::OutResult {
313 match transfer_type {
314 TransferType::Interrupt => {
315 self.recv_buffer
320 .take()
321 .map_or(hil::usb::OutResult::Delay, |buf| {
322 let copy_length = cmp::min(packet_bytes as usize, buf.len());
324
325 let packet = &self.buffers[OUT_BUFFER].buf;
327 for i in 0..copy_length {
328 buf[i] = packet[i].get();
329 }
330
331 self.client.map(move |client| {
333 client.packet_received(Ok(()), buf, endpoint);
334 });
335
336 hil::usb::OutResult::Ok
337 })
338 }
339 TransferType::Bulk | TransferType::Control | TransferType::Isochronous => {
340 panic!("Transfer protocol not supported by CTAP v2");
341 }
342 }
343 }
344
345 fn packet_transmitted(&'a self, endpoint: usize) {
346 self.send_buffer.take().map(|buf| {
347 self.client.map(move |client| {
348 client.packet_transmitted(Ok(()), buf, endpoint);
349 });
350 });
351 }
352}