1use core::cell::Cell;
10
11use super::descriptors::{
12 self, Buffer8, DeviceDescriptor, EndpointAddress, EndpointDescriptor, TransferDirection,
13};
14use super::usbc_client_ctrl::ClientCtrl;
15
16use kernel::debug;
17use kernel::hil;
18use kernel::hil::usb::TransferType;
19use kernel::utilities::cells::VolatileCell;
20
21const VENDOR_ID: u16 = 0x6667;
22const PRODUCT_ID: u16 = 0xabcd;
23
24static LANGUAGES: &[u16; 1] = &[
25 0x0409, ];
27
28static STRINGS: &[&str] = &[
29 "XYZ Corp.", "The Zorpinator", "Serial No. 5", ];
33
34pub const MAX_CTRL_PACKET_SIZE_SAM4L: u8 = 8;
36pub const MAX_CTRL_PACKET_SIZE_NRF52840: u8 = 64;
38pub const MAX_CTRL_PACKET_SIZE_EARLGREY: u8 = 64;
40
41const N_ENDPOINTS: usize = 2;
42
43pub struct Client<'a, C: 'a> {
44 client_ctrl: ClientCtrl<'a, 'static, C>,
45
46 buffers: [Buffer8; N_ENDPOINTS],
48
49 echo_buf: [Cell<u8>; 8], echo_len: Cell<usize>,
53 delayed_out: Cell<bool>,
54}
55
56impl<'a, C: hil::usb::UsbController<'a>> Client<'a, C> {
57 pub fn new(controller: &'a C, max_ctrl_packet_size: u8) -> Self {
58 let interfaces: &mut [descriptors::InterfaceDescriptor] =
59 &mut [descriptors::InterfaceDescriptor {
60 interface_number: 0,
61 alternate_setting: 0,
62 num_endpoints: 0, interface_class: 0xff, interface_subclass: 0xab,
65 interface_protocol: 0,
66 string_index: 0,
67 }];
68
69 let endpoints: &[&[EndpointDescriptor]] = &mut [&[
70 EndpointDescriptor {
71 endpoint_address: EndpointAddress::new_const(1, TransferDirection::DeviceToHost),
72 transfer_type: TransferType::Bulk,
73 max_packet_size: 8,
74 interval: 0,
75 },
76 EndpointDescriptor {
77 endpoint_address: EndpointAddress::new_const(2, TransferDirection::HostToDevice),
78 transfer_type: TransferType::Bulk,
79 max_packet_size: 8,
80 interval: 0,
81 },
82 ]];
83
84 let (device_descriptor_buffer, other_descriptor_buffer) =
85 descriptors::create_descriptor_buffers(
86 DeviceDescriptor {
87 vendor_id: VENDOR_ID,
88 product_id: PRODUCT_ID,
89 manufacturer_string: 1,
90 product_string: 2,
91 serial_number_string: 3,
92 max_packet_size_ep0: max_ctrl_packet_size,
93 ..DeviceDescriptor::default()
94 },
95 descriptors::ConfigurationDescriptor::default(),
96 interfaces,
97 endpoints,
98 None, None, );
101
102 Client {
103 client_ctrl: ClientCtrl::new(
104 controller,
105 device_descriptor_buffer,
106 other_descriptor_buffer,
107 None, None, LANGUAGES,
110 STRINGS,
111 ),
112 buffers: Default::default(),
113 echo_buf: Default::default(),
114 echo_len: Cell::new(0),
115 delayed_out: Cell::new(false),
116 }
117 }
118
119 fn alert_full(&'a self) {
120 self.controller().endpoint_resume_in(1);
122 }
123
124 fn alert_empty(&'a self) {
125 if self.delayed_out.take() {
128 self.controller().endpoint_resume_out(2);
129 }
130 }
131
132 #[inline]
133 fn controller(&'a self) -> &'a C {
134 self.client_ctrl.controller()
135 }
136
137 #[inline]
138 fn buffer(&'a self, i: usize) -> &'a [VolatileCell<u8>; 8] {
139 &self.buffers[i - 1].buf
140 }
141}
142
143impl<'a, C: hil::usb::UsbController<'a>> hil::usb::Client<'a> for Client<'a, C> {
144 fn enable(&'a self) {
145 self.client_ctrl.enable();
147
148 self.controller().endpoint_set_in_buffer(1, self.buffer(1));
150 self.controller().endpoint_in_enable(TransferType::Bulk, 1);
151
152 self.controller().endpoint_set_out_buffer(2, self.buffer(2));
154 self.controller().endpoint_out_enable(TransferType::Bulk, 2);
155 }
156
157 fn attach(&'a self) {
158 self.client_ctrl.attach();
159 }
160
161 fn bus_reset(&'a self) {
162 debug!("Bus reset");
166
167 self.echo_len.set(0);
169 self.delayed_out.set(false);
170 }
171
172 fn ctrl_setup(&'a self, endpoint: usize) -> hil::usb::CtrlSetupResult {
174 self.client_ctrl.ctrl_setup(endpoint)
175 }
176
177 fn ctrl_in(&'a self, endpoint: usize) -> hil::usb::CtrlInResult {
179 self.client_ctrl.ctrl_in(endpoint)
180 }
181
182 fn ctrl_out(&'a self, endpoint: usize, packet_bytes: u32) -> hil::usb::CtrlOutResult {
184 self.client_ctrl.ctrl_out(endpoint, packet_bytes)
185 }
186
187 fn ctrl_status(&'a self, endpoint: usize) {
188 self.client_ctrl.ctrl_status(endpoint)
189 }
190
191 fn ctrl_status_complete(&'a self, endpoint: usize) {
193 self.client_ctrl.ctrl_status_complete(endpoint)
194 }
195
196 fn packet_in(&'a self, transfer_type: TransferType, endpoint: usize) -> hil::usb::InResult {
198 match transfer_type {
199 TransferType::Interrupt => {
200 debug!("interrupt_in({}) not implemented", endpoint);
201 hil::usb::InResult::Error
202 }
203 TransferType::Bulk => {
204 let packet_bytes = self.echo_len.get();
206 if packet_bytes > 0 {
207 let packet = self.buffer(endpoint);
209 for i in 0..packet_bytes {
210 packet[i].set(self.echo_buf[i].get());
211 }
212 self.echo_len.set(0);
213
214 self.alert_empty();
216
217 hil::usb::InResult::Packet(packet_bytes)
218 } else {
219 hil::usb::InResult::Delay
221 }
222 }
223 TransferType::Control | TransferType::Isochronous => unreachable!(),
224 }
225 }
226
227 fn packet_out(
229 &'a self,
230 transfer_type: TransferType,
231 endpoint: usize,
232 packet_bytes: u32,
233 ) -> hil::usb::OutResult {
234 match transfer_type {
235 TransferType::Interrupt => {
236 debug!("interrupt_out({}) not implemented", endpoint);
237 hil::usb::OutResult::Error
238 }
239 TransferType::Bulk => {
240 let new_len = packet_bytes as usize;
242 let current_len = self.echo_len.get();
243 let total_len = current_len + new_len;
244
245 if total_len > self.echo_buf.len() {
246 self.delayed_out.set(true);
249 hil::usb::OutResult::Delay
250 } else if new_len > 0 {
251 let packet = self.buffer(endpoint);
253 for i in 0..new_len {
254 self.echo_buf[current_len + i].set(packet[i].get());
255 }
256 self.echo_len.set(total_len);
257
258 self.alert_full();
260 hil::usb::OutResult::Ok
261 } else {
262 debug!("Ignoring zero-length OUT packet");
263 hil::usb::OutResult::Ok
264 }
265 }
266 TransferType::Control | TransferType::Isochronous => unreachable!(),
267 }
268 }
269
270 fn packet_transmitted(&'a self, _endpoint: usize) {
271 }
273}