xref: /aosp_15_r20/external/coreboot/payloads/libpayload/drivers/udc/udc.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /*
2  *
3  * Copyright (C) 2015 Google Inc.
4  *
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.
15  *
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.
27  */
28 
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>
38 
39 #include <udc/udc.h>
40 
41 #ifdef DEBUG
42 #define debug(x...) printf(x)
43 #else
44 #define debug(x...) do {} while (0)
45 #endif
46 
47 #define min(a, b) (((a) < (b)) ? (a) : (b))
48 
49 static unsigned short strings_lang_id = 0;
50 static unsigned char strings_count = 0;
51 static const char **strings;
52 
udc_add_strings(unsigned short lang_id,unsigned char count,const char ** str)53 void udc_add_strings(unsigned short lang_id, unsigned char count,
54 	const char **str)
55 {
56 	strings_lang_id = lang_id;
57 	strings_count = count;
58 	strings = str;
59 }
60 
61 /* determine if an additional zero length packet is necessary for
62  * a transfer */
zlp(struct usbdev_ctrl * this,const int epnum,const int len,const int explen)63 static unsigned int zlp(struct usbdev_ctrl *this, const int epnum,
64 	const int len, const int explen)
65 {
66 	const unsigned int mps = this->ep_mps[epnum][1];
67 
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;
77 
78 	/* otherwise we need an extra zero length packet */
79 	return 1;
80 }
81 
fetch_config(struct usbdev_ctrl * this,int id)82 static struct usbdev_configuration *fetch_config(struct usbdev_ctrl *this,
83 	int id)
84 {
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;
91 	}
92 	return NULL;
93 }
94 
cease_operation(struct usbdev_ctrl * this)95 static void cease_operation(struct usbdev_ctrl *this)
96 {
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);
102 	}
103 
104 }
105 
enable_interface(struct usbdev_ctrl * this,int iface_num)106 static void enable_interface(struct usbdev_ctrl *this, int iface_num)
107 {
108 	struct usbdev_configuration *config = this->current_config;
109 	struct usbdev_interface *iface = &config->interfaces[iface_num];
110 
111 	/* first: shut down all endpoints except EP0 */
112 	cease_operation(this);
113 
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;
124 		}
125 		int ep_type = iface->eps[i].bmAttributes & 0x3;
126 		this->start_ep(this, ep, in_dir, ep_type, mps);
127 	}
128 
129 	this->current_iface = iface;
130 
131 	// gadget specific configuration
132 	if (iface->init)
133 		iface->init(this);
134 }
135 
136 /**
137  * handle default control transfers on EP 0
138  *
139  * returns 1 if transfer was handled
140  */
setup_ep0(struct usbdev_ctrl * this,dev_req_t * dr)141 static int setup_ep0(struct usbdev_ctrl *this, dev_req_t *dr)
142 {
143 	if ((dr->bmRequestType == 0x00) &&
144 	    (dr->bRequest == SET_ADDRESS)) {
145 		this->set_address(this, dr->wValue & 0x7f);
146 
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);
155 
156 		if (dr->wValue == 0)
157 			cease_operation(this);
158 
159 		if (config == NULL) {
160 			this->stall(this, 0, 0, 1);
161 			this->stall(this, 0, 1, 1);
162 			return 1;
163 		}
164 
165 		/* status phase IN */
166 		this->enqueue_packet(this, 0, 1, NULL, 0, 0, 0);
167 
168 		this->current_config = config;
169 		this->current_config_id = dr->wValue;
170 
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;
180 
181 		/* data phase IN */
182 		this->enqueue_packet(this, 0, 1, res, min(1, dr->wLength),
183 			0, 1);
184 
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);
196 
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);
208 
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;
218 
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;
228 
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;
240 
241 		/* data phase IN */
242 		this->enqueue_packet(this, 0, 1, res,
243 			min(2, dr->wLength), 0, 1);
244 
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;
255 
256 		res[1] = 0;
257 
258 		/* data phase IN */
259 		this->enqueue_packet(this, 0, 1, res,
260 			min(2, dr->wLength), 0, 1);
261 
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.
273 		 */
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;
280 		}
281 		debug("descriptor found, should be %d bytes\n",
282 			config->descriptor.wTotalLength);
283 
284 		uint8_t *data = dma_malloc(config->descriptor.wTotalLength);
285 		uint8_t *head = data;
286 
287 		memcpy(head, &config->descriptor,
288 			sizeof(configuration_descriptor_t));
289 		head += sizeof(configuration_descriptor_t);
290 
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);
301 			}
302 		}
303 		int size = config->descriptor.wTotalLength;
304 		assert((head - data) == config->descriptor.wTotalLength);
305 
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);
310 
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;
322 
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),
333 				1);
334 
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;
340 
341 			int lang = dr->wIndex;
342 			if (lang != strings_lang_id)
343 				return 0;
344 
345 			if (id > strings_count)
346 				return 0;
347 
348 			int s_len = strlen(strings[id]);
349 			int d_len = s_len * 2;
350 
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];
358 
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),
364 				1);
365 
366 			/* status phase OUT */
367 			this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
368 		}
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;
377 
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);
382 
383 		/* status phase OUT */
384 		this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
385 		return 1;
386 	}
387 	return 0;
388 }
389 
udc_add_gadget(struct usbdev_ctrl * this,struct usbdev_configuration * config)390 void udc_add_gadget(struct usbdev_ctrl *this,
391 	struct usbdev_configuration *config)
392 {
393 	int i, size;
394 	SLIST_INSERT_HEAD(&this->configs, config, list);
395 
396 	size = sizeof(configuration_descriptor_t);
397 
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);
402 	}
403 	config->descriptor.wTotalLength = size;
404 	config->descriptor.bConfigurationValue = ++this->config_count;
405 }
406 
udc_handle_setup(struct usbdev_ctrl * this,int ep,dev_req_t * dr)407 void udc_handle_setup(struct usbdev_ctrl *this, int ep, dev_req_t *dr)
408 {
409 	if ((ep == 0) && setup_ep0(this, dr))
410 		return;
411 
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;
416 
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);
420 }
421