soc/intel/cmn/cse: Deprecate CONFIG_SOC_INTEL_CSE_RW_VERSION
[coreboot2.git] / payloads / libpayload / drivers / udc / udc.c
blobd2dade30a2cd961e99cf4afa68613e1d53b3d510
1 /*
3 * Copyright (C) 2015 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include <libpayload.h>
30 #include <arch/cache.h>
31 #include <assert.h>
32 #include <endian.h>
33 #include <queue.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <usb/usb.h>
39 #include <udc/udc.h>
41 #ifdef DEBUG
42 #define debug(x...) printf(x)
43 #else
44 #define debug(x...) do {} while (0)
45 #endif
47 #define min(a, b) (((a) < (b)) ? (a) : (b))
49 static unsigned short strings_lang_id = 0;
50 static unsigned char strings_count = 0;
51 static const char **strings;
53 void udc_add_strings(unsigned short lang_id, unsigned char count,
54 const char **str)
56 strings_lang_id = lang_id;
57 strings_count = count;
58 strings = str;
61 /* determine if an additional zero length packet is necessary for
62 * a transfer */
63 static unsigned int zlp(struct usbdev_ctrl *this, const int epnum,
64 const int len, const int explen)
66 const unsigned int mps = this->ep_mps[epnum][1];
68 /* zero length transfers are handled explicitly */
69 if (len == 0)
70 return 0;
71 /* host expects exactly the right amount, so no zlp necessary */
72 if (len == explen)
73 return 0;
74 /* last packet will be short -> host knows that transfer is over */
75 if ((len % mps) != 0)
76 return 0;
78 /* otherwise we need an extra zero length packet */
79 return 1;
82 static struct usbdev_configuration *fetch_config(struct usbdev_ctrl *this,
83 int id)
85 struct usbdev_configuration *config;
86 SLIST_FOREACH(config, &this->configs, list) {
87 debug("checking descriptor %d\n",
88 config->descriptor.bConfigurationValue);
89 if (config->descriptor.bConfigurationValue == id)
90 return config;
92 return NULL;
95 static void cease_operation(struct usbdev_ctrl *this)
97 int i;
98 for (i = 1; i < 16; i++) {
99 /* disable endpoints */
100 this->halt_ep(this, i, 0);
101 this->halt_ep(this, i, 1);
106 static void enable_interface(struct usbdev_ctrl *this, int iface_num)
108 struct usbdev_configuration *config = this->current_config;
109 struct usbdev_interface *iface = &config->interfaces[iface_num];
111 /* first: shut down all endpoints except EP0 */
112 cease_operation(this);
114 /* now enable all configured endpoints */
115 int epcount = iface->descriptor.bNumEndpoints;
116 int i;
117 for (i = 0; i < epcount; i++) {
118 int ep = iface->eps[i].bEndpointAddress;
119 int mps = iface->eps[i].wMaxPacketSize;
120 int in_dir = 0;
121 if (ep & 0x80) {
122 in_dir = 1;
123 ep &= 0x7f;
125 int ep_type = iface->eps[i].bmAttributes & 0x3;
126 this->start_ep(this, ep, in_dir, ep_type, mps);
129 this->current_iface = iface;
131 // gadget specific configuration
132 if (iface->init)
133 iface->init(this);
137 * handle default control transfers on EP 0
139 * returns 1 if transfer was handled
141 static int setup_ep0(struct usbdev_ctrl *this, dev_req_t *dr)
143 if ((dr->bmRequestType == 0x00) &&
144 (dr->bRequest == SET_ADDRESS)) {
145 this->set_address(this, dr->wValue & 0x7f);
147 /* status phase IN */
148 this->enqueue_packet(this, 0, 1, NULL, 0, 0, 0);
149 return 1;
150 } else
151 if ((dr->bmRequestType == 0x00) &&
152 (dr->bRequest == SET_CONFIGURATION)) {
153 struct usbdev_configuration *config =
154 fetch_config(this, dr->wValue);
156 if (dr->wValue == 0)
157 cease_operation(this);
159 if (config == NULL) {
160 this->stall(this, 0, 0, 1);
161 this->stall(this, 0, 1, 1);
162 return 1;
165 /* status phase IN */
166 this->enqueue_packet(this, 0, 1, NULL, 0, 0, 0);
168 this->current_config = config;
169 this->current_config_id = dr->wValue;
171 /* activate first interface */
172 enable_interface(this, 0);
173 this->initialized = 1;
174 return 1;
175 } else
176 if ((dr->bmRequestType == 0x80) &&
177 (dr->bRequest == GET_CONFIGURATION)) {
178 unsigned char *res = dma_malloc(1);
179 res[0] = this->current_config_id;
181 /* data phase IN */
182 this->enqueue_packet(this, 0, 1, res, min(1, dr->wLength),
183 0, 1);
185 /* status phase OUT */
186 this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
187 return 1;
188 } else
189 // ENDPOINT_HALT
190 if ((dr->bmRequestType == 0x02) && // endpoint
191 (dr->bRequest == CLEAR_FEATURE) &&
192 (dr->wValue == 0)) {
193 int ep = dr->wIndex;
194 /* clear STALL */
195 this->stall(this, ep & 0xf, ep & 0x80, 0);
197 /* status phase IN */
198 this->enqueue_packet(this, 0, 1, NULL, 0, 0, 0);
199 return 1;
200 } else
201 // ENDPOINT_HALT
202 if ((dr->bmRequestType == 0x02) && // endpoint
203 (dr->bRequest == SET_FEATURE) &&
204 (dr->wValue == 0)) {
205 int ep = dr->wIndex;
206 /* set STALL */
207 this->stall(this, ep & 0xf, ep & 0x80, 1);
209 /* status phase IN */
210 this->enqueue_packet(this, 0, 1, NULL, 0, 0, 0);
211 return 1;
212 } else
213 // DEVICE_REMOTE_WAKEUP
214 if ((dr->bmRequestType == 0x00) &&
215 (dr->bRequest == CLEAR_FEATURE) &&
216 (dr->wValue == 1)) {
217 this->remote_wakeup = 0;
219 /* status phase IN */
220 this->enqueue_packet(this, 0, 1, NULL, 0, 0, 0);
221 return 1;
222 } else
223 // DEVICE_REMOTE_WAKEUP
224 if ((dr->bmRequestType == 0x00) &&
225 (dr->bRequest == SET_FEATURE) &&
226 (dr->wValue == 1)) {
227 this->remote_wakeup = 1;
229 /* status phase IN */
230 this->enqueue_packet(this, 0, 1, NULL, 0, 0, 0);
231 return 1;
232 } else
233 if ((dr->bmRequestType == 0x82) && // endpoint
234 (dr->bRequest == GET_STATUS)) {
235 unsigned char *res = dma_malloc(2);
236 int ep = dr->wIndex;
237 /* is EP halted? */
238 res[0] = this->ep_halted[ep & 0xf][(ep & 0x80) ? 1 : 0];
239 res[1] = 0;
241 /* data phase IN */
242 this->enqueue_packet(this, 0, 1, res,
243 min(2, dr->wLength), 0, 1);
245 // status phase OUT
246 this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
247 return 1;
248 } else
249 if ((dr->bmRequestType == 0x80) &&
250 (dr->bRequest == GET_STATUS)) {
251 unsigned char *res = dma_malloc(2);
252 res[0] = 1; // self powered
253 if (this->remote_wakeup)
254 res[0] |= 2;
256 res[1] = 0;
258 /* data phase IN */
259 this->enqueue_packet(this, 0, 1, res,
260 min(2, dr->wLength), 0, 1);
262 // status phase OUT
263 this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
264 return 1;
265 } else
266 if ((dr->bmRequestType == 0x80) &&
267 (dr->bRequest == GET_DESCRIPTOR) &&
268 ((dr->wValue & 0xff00) == 0x0200)) {
269 int i, j;
270 /* config descriptor #id
271 * since config = 0 is undefined, but descriptors
272 * should start at 0, add 1 to have them match up.
274 int id = (dr->wValue & 0xff) + 1;
275 struct usbdev_configuration *config = fetch_config(this, id);
276 if (config == NULL) {
277 this->stall(this, 0, 0, 1);
278 this->stall(this, 0, 1, 1);
279 return 1;
281 debug("descriptor found, should be %d bytes\n",
282 config->descriptor.wTotalLength);
284 uint8_t *data = dma_malloc(config->descriptor.wTotalLength);
285 uint8_t *head = data;
287 memcpy(head, &config->descriptor,
288 sizeof(configuration_descriptor_t));
289 head += sizeof(configuration_descriptor_t);
291 for (i = 0; i < config->descriptor.bNumInterfaces; i++) {
292 memcpy(head, &config->interfaces[i].descriptor,
293 sizeof(interface_descriptor_t));
294 head += sizeof(interface_descriptor_t);
295 for (j = 0;
296 j < config->interfaces[i].descriptor.bNumEndpoints;
297 j++) {
298 memcpy(head, &config->interfaces[i].eps[j],
299 sizeof(endpoint_descriptor_t));
300 head += sizeof(endpoint_descriptor_t);
303 int size = config->descriptor.wTotalLength;
304 assert((head - data) == config->descriptor.wTotalLength);
306 /* data phase IN */
307 this->enqueue_packet(this, 0, 1, data,
308 min(size, dr->wLength),
309 zlp(this, 0, size, dr->wLength), 1);
311 /* status phase OUT */
312 this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
313 return 1;
314 } else
315 if ((dr->bmRequestType == 0x80) &&
316 (dr->bRequest == GET_DESCRIPTOR) &&
317 ((dr->wValue & 0xff00) == 0x0300)) {
318 int id = (dr->wValue & 0xff);
319 if (id == 0) {
320 if (strings_lang_id == 0)
321 return 0;
323 uint8_t *data = dma_malloc(4);
324 data[0] = 0x04; // length
325 data[1] = 0x03; // string descriptor
326 data[2] = strings_lang_id & 0xff;
327 data[3] = strings_lang_id >> 8;
328 /* data phase IN */
329 this->enqueue_packet(this, 0, 1,
330 data,
331 min(data[0], dr->wLength),
332 zlp(this, 0, data[0], dr->wLength),
335 /* status phase OUT */
336 this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
337 } else {
338 if (strings_lang_id == 0)
339 return 0;
341 int lang = dr->wIndex;
342 if (lang != strings_lang_id)
343 return 0;
345 if (id > strings_count)
346 return 0;
348 int s_len = strlen(strings[id]);
349 int d_len = s_len * 2;
351 uint8_t *data = dma_malloc(d_len + 2);
352 memset(data, 0, d_len + 2);
353 data[0] = d_len + 2; // length
354 data[1] = 0x03; // string descriptor
355 int i;
356 for (i = 0; i < s_len; i++)
357 data[i * 2 + 2] = strings[id][i];
359 /* data phase IN */
360 this->enqueue_packet(this, 0, 1,
361 data,
362 min(d_len + 2, dr->wLength),
363 zlp(this, 0, d_len + 2, dr->wLength),
366 /* status phase OUT */
367 this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
369 return 1;
370 } else
371 if ((dr->bmRequestType == 0x80) &&
372 (dr->bRequest == GET_DESCRIPTOR) &&
373 ((dr->wValue & 0xff00) == 0x0100)) {
374 device_descriptor_t *dd = dma_malloc(sizeof(*dd));
375 memcpy(dd, &this->device_descriptor, sizeof(*dd));
376 dd->bNumConfigurations = this->config_count;
378 /* data phase IN */
379 this->enqueue_packet(this, 0, 1, (void *)dd,
380 min(sizeof(*dd), dr->wLength),
381 zlp(this, 0, sizeof(*dd), dr->wLength), 1);
383 /* status phase OUT */
384 this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
385 return 1;
387 return 0;
390 void udc_add_gadget(struct usbdev_ctrl *this,
391 struct usbdev_configuration *config)
393 int i, size;
394 SLIST_INSERT_HEAD(&this->configs, config, list);
396 size = sizeof(configuration_descriptor_t);
398 for (i = 0; i < config->descriptor.bNumInterfaces; i++) {
399 size += sizeof(config->interfaces[i].descriptor);
400 size += config->interfaces[i].descriptor.bNumEndpoints *
401 sizeof(endpoint_descriptor_t);
403 config->descriptor.wTotalLength = size;
404 config->descriptor.bConfigurationValue = ++this->config_count;
407 void udc_handle_setup(struct usbdev_ctrl *this, int ep, dev_req_t *dr)
409 if ((ep == 0) && setup_ep0(this, dr))
410 return;
412 if (this->current_config &&
413 this->current_config->interfaces[0].handle_setup &&
414 this->current_config->interfaces[0].handle_setup(this, ep, dr))
415 return;
417 /* no successful SETUP transfer should end up here, report error */
418 this->halt_ep(this, ep, 0);
419 this->halt_ep(this, ep, 1);