1 /*
2  * Copyright (c) 2023,2025 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/usb/usbh.h>
8 #include <zephyr/sys/byteorder.h>
9 
10 #include "usbh_device.h"
11 #include "usbh_ch9.h"
12 
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(usbh_dev, CONFIG_USBH_LOG_LEVEL);
15 
16 K_MEM_SLAB_DEFINE_STATIC(usb_device_slab, sizeof(struct usb_device),
17 			 CONFIG_USBH_USB_DEVICE_MAX, sizeof(void *));
18 
19 K_HEAP_DEFINE(usb_device_heap, CONFIG_USBH_USB_DEVICE_HEAP);
20 
usbh_device_alloc(struct usbh_contex * const uhs_ctx)21 struct usb_device *usbh_device_alloc(struct usbh_contex *const uhs_ctx)
22 {
23 	struct usb_device *udev;
24 
25 	if (k_mem_slab_alloc(&usb_device_slab, (void **)&udev, K_NO_WAIT)) {
26 		LOG_ERR("Failed to allocate USB device memory");
27 		return NULL;
28 	}
29 
30 	memset(udev, 0, sizeof(struct usb_device));
31 	udev->ctx = uhs_ctx;
32 	sys_dlist_append(&uhs_ctx->udevs, &udev->node);
33 	k_mutex_init(&udev->mutex);
34 
35 	return udev;
36 }
37 
usbh_device_free(struct usb_device * const udev)38 void usbh_device_free(struct usb_device *const udev)
39 {
40 	struct usbh_contex *const uhs_ctx = udev->ctx;
41 
42 	sys_bitarray_clear_bit(uhs_ctx->addr_ba, udev->addr);
43 	sys_dlist_remove(&udev->node);
44 	if (udev->cfg_desc != NULL) {
45 		k_heap_free(&usb_device_heap, udev->cfg_desc);
46 	}
47 
48 	k_mem_slab_free(&usb_device_slab, (void *)udev);
49 }
50 
usbh_device_get_any(struct usbh_contex * const uhs_ctx)51 struct usb_device *usbh_device_get_any(struct usbh_contex *const uhs_ctx)
52 {
53 	sys_dnode_t *const node = sys_dlist_peek_head(&uhs_ctx->udevs);
54 	struct usb_device *udev;
55 
56 	udev = SYS_DLIST_CONTAINER(node, udev, node);
57 
58 	return udev;
59 }
60 
usbh_device_get(struct usbh_contex * const uhs_ctx,const uint8_t addr)61 struct usb_device *usbh_device_get(struct usbh_contex *const uhs_ctx, const uint8_t addr)
62 {
63 	struct usb_device *udev;
64 
65 	SYS_DLIST_FOR_EACH_CONTAINER(&uhs_ctx->udevs, udev, node) {
66 		if (addr == udev->addr) {
67 			return udev;
68 		}
69 	}
70 
71 	return NULL;
72 }
73 
validate_device_mps0(const struct usb_device * const udev)74 static int validate_device_mps0(const struct usb_device *const udev)
75 {
76 	const uint8_t mps0 = udev->dev_desc.bMaxPacketSize0;
77 
78 	if (udev->speed == USB_SPEED_SPEED_SS || udev->speed == USB_SPEED_SPEED_LS) {
79 		LOG_ERR("USB device speed not supported");
80 		return -ENOTSUP;
81 	}
82 
83 	if (udev->speed == USB_SPEED_SPEED_HS) {
84 		if (mps0 != 64) {
85 			LOG_ERR("HS device has wrong bMaxPacketSize0 %u", mps0);
86 			return -EINVAL;
87 		}
88 	}
89 
90 	if (udev->speed == USB_SPEED_SPEED_FS) {
91 		if (mps0 != 8 && mps0 != 16 && mps0 != 32 && mps0 != 64) {
92 			LOG_ERR("FS device has wrong bMaxPacketSize0 %u", mps0);
93 			return -EINVAL;
94 		}
95 	}
96 
97 	return 0;
98 }
99 
alloc_device_address(struct usb_device * const udev,uint8_t * const addr)100 static int alloc_device_address(struct usb_device *const udev, uint8_t *const addr)
101 {
102 	struct usbh_contex *const uhs_ctx = udev->ctx;
103 	int val;
104 	int err;
105 
106 	for (unsigned int i = 1; i < 128; i++) {
107 		err = sys_bitarray_test_and_set_bit(uhs_ctx->addr_ba, i, &val);
108 		if (err) {
109 			return err;
110 		}
111 
112 		if (val == 0) {
113 			*addr = i;
114 			return 0;
115 		}
116 	}
117 
118 	return -ENOENT;
119 }
120 
121 enum ep_op {
122 	EP_OP_TEST, /* Verify endpont descriptor */
123 	EP_OP_UP,   /* Enable endpoint and update endpoint pointers */
124 	EP_OP_DOWN, /* Disable endpoint and update endpoint pointers */
125 };
126 
assign_ep_desc_ptr(struct usb_device * const udev,const uint8_t ep,void * const ptr)127 static void assign_ep_desc_ptr(struct usb_device *const udev,
128 			       const uint8_t ep, void *const ptr)
129 {
130 	uint8_t idx = USB_EP_GET_IDX(ep) & 0xF;
131 
132 	if (USB_EP_DIR_IS_IN(ep)) {
133 		udev->ep_in[idx].desc = ptr;
134 	} else {
135 		udev->ep_out[idx].desc = ptr;
136 	}
137 }
138 
handle_ep_op(struct usb_device * const udev,const enum ep_op op,const uint8_t ep,struct usb_ep_descriptor * const ep_desc)139 static int handle_ep_op(struct usb_device *const udev,
140 			const enum ep_op op, const uint8_t ep,
141 			struct usb_ep_descriptor *const ep_desc)
142 {
143 	switch (op) {
144 	case EP_OP_TEST:
145 		break;
146 	case EP_OP_UP:
147 		if (ep_desc == NULL) {
148 			return -ENOTSUP;
149 		}
150 
151 		assign_ep_desc_ptr(udev, ep_desc->bEndpointAddress, ep_desc);
152 		break;
153 	case EP_OP_DOWN:
154 		assign_ep_desc_ptr(udev, ep, NULL);
155 		break;
156 	}
157 
158 	return 0;
159 }
160 
device_interface_modify(struct usb_device * const udev,const enum ep_op op,const uint8_t iface,const uint8_t alt)161 static int device_interface_modify(struct usb_device *const udev,
162 				   const enum ep_op op,
163 				   const uint8_t iface, const uint8_t alt)
164 {
165 	struct usb_cfg_descriptor *cfg_desc = udev->cfg_desc;
166 	struct usb_if_descriptor *if_desc = NULL;
167 	struct usb_ep_descriptor *ep_desc;
168 	struct usb_desc_header *dhp;
169 	bool found_iface = false;
170 	void *desc_end;
171 	int err;
172 
173 	dhp = udev->ifaces[iface].dhp;
174 	desc_end = (void *)((uint8_t *)udev->cfg_desc + cfg_desc->wTotalLength);
175 
176 	while (dhp != NULL && (void *)dhp < desc_end) {
177 		if (dhp->bDescriptorType == USB_DESC_INTERFACE) {
178 			if_desc = (struct usb_if_descriptor *)dhp;
179 
180 			if (found_iface) {
181 				break;
182 			}
183 
184 			if (if_desc->bInterfaceNumber == iface &&
185 			    if_desc->bAlternateSetting == alt) {
186 				found_iface = true;
187 				LOG_DBG("Found interface %u alternate %u", iface, alt);
188 				if (if_desc->bNumEndpoints == 0) {
189 					LOG_DBG("No endpoints, skip interface");
190 					break;
191 				}
192 			}
193 		}
194 
195 		if (dhp->bDescriptorType == USB_DESC_ENDPOINT && found_iface) {
196 			ep_desc = (struct usb_ep_descriptor *)dhp;
197 			err = handle_ep_op(udev, op, ep_desc->bEndpointAddress, ep_desc);
198 			if (err) {
199 				return err;
200 			}
201 
202 			LOG_INF("Modify interface %u ep 0x%02x by op %u",
203 				iface, ep_desc->bEndpointAddress, op);
204 		}
205 
206 		dhp = (void *)((uint8_t *)dhp + dhp->bLength);
207 	}
208 
209 
210 	return found_iface ? 0 : -ENODATA;
211 }
212 
usbh_device_interface_set(struct usb_device * const udev,const uint8_t iface,const uint8_t alt,const bool dry)213 int usbh_device_interface_set(struct usb_device *const udev,
214 			      const uint8_t iface, const uint8_t alt,
215 			      const bool dry)
216 {
217 	uint8_t cur_alt;
218 	int err;
219 
220 	if (iface > UHC_INTERFACES_MAX) {
221 		LOG_ERR("Unsupported number of interfaces");
222 		return -EINVAL;
223 	}
224 
225 	err = k_mutex_lock(&udev->mutex, K_NO_WAIT);
226 	if (err) {
227 		LOG_ERR("Failed to lock USB device");
228 		return err;
229 	}
230 
231 	if (!dry) {
232 		err = usbh_req_set_alt(udev, iface, alt);
233 		if (err) {
234 			LOG_ERR("Set Interface %u alternate %u request failed", iface, alt);
235 			goto error;
236 		}
237 	}
238 
239 	cur_alt = udev->ifaces[iface].alternate;
240 	LOG_INF("Set Interfaces %u, alternate %u -> %u", iface, cur_alt, alt);
241 	if (alt == cur_alt) {
242 		LOG_DBG("Already active interface alternate");
243 		goto error;
244 	}
245 
246 	/* Test if interface and interface alternate exist */
247 	err = device_interface_modify(udev, EP_OP_TEST, iface, alt);
248 	if (err) {
249 		LOG_ERR("No interface %u with alternate %u", iface, alt);
250 		goto error;
251 	}
252 
253 	/* Shutdown current interface alternate */
254 	err = device_interface_modify(udev, EP_OP_DOWN, iface, cur_alt);
255 	if (err) {
256 		LOG_ERR("Failed to shutdown interface %u alternate %u", iface, alt);
257 		goto error;
258 	}
259 
260 	/* Setup new interface alternate */
261 	err = device_interface_modify(udev, EP_OP_UP, iface, alt);
262 	if (err) {
263 		LOG_ERR("Failed to setup interface %u alternate %u", iface, cur_alt);
264 		goto error;
265 	}
266 
267 	udev->ifaces[iface].alternate = alt;
268 
269 error:
270 	k_mutex_unlock(&udev->mutex);
271 
272 	return 0;
273 }
274 
parse_configuration_descriptor(struct usb_device * const udev)275 static int parse_configuration_descriptor(struct usb_device *const udev)
276 {
277 	struct usb_cfg_descriptor *cfg_desc = udev->cfg_desc;
278 	struct usb_association_descriptor *iad = NULL;
279 	struct usb_if_descriptor *if_desc = NULL;
280 	struct usb_ep_descriptor *ep_desc;
281 	struct usb_desc_header *dhp;
282 	uint8_t tmp_nif = 0;
283 	void *desc_end;
284 
285 	dhp = (void *)((uint8_t *)udev->cfg_desc + cfg_desc->bLength);
286 	desc_end = (void *)((uint8_t *)udev->cfg_desc + cfg_desc->wTotalLength);
287 
288 	while ((dhp->bDescriptorType != 0 || dhp->bLength != 0) && (void *)dhp < desc_end) {
289 		if (dhp->bDescriptorType == USB_DESC_INTERFACE_ASSOC) {
290 			iad = (struct usb_association_descriptor *)dhp;
291 			LOG_DBG("bFirstInterface %u", iad->bFirstInterface);
292 		}
293 
294 		if (dhp->bDescriptorType == USB_DESC_INTERFACE) {
295 			if_desc = (struct usb_if_descriptor *)dhp;
296 			LOG_DBG("bInterfaceNumber %u bAlternateSetting %u",
297 				if_desc->bInterfaceNumber, if_desc->bAlternateSetting);
298 
299 			if (if_desc->bAlternateSetting == 0) {
300 				if (tmp_nif >= UHC_INTERFACES_MAX) {
301 					LOG_ERR("Unsupported number of interfaces");
302 					return -EINVAL;
303 				}
304 
305 				udev->ifaces[tmp_nif].dhp = dhp;
306 				tmp_nif++;
307 			}
308 		}
309 
310 		if (dhp->bDescriptorType == USB_DESC_ENDPOINT) {
311 			ep_desc = (struct usb_ep_descriptor *)dhp;
312 
313 			ep_desc->wMaxPacketSize = sys_le16_to_cpu(ep_desc->wMaxPacketSize);
314 			LOG_DBG("bEndpointAddress 0x%02x wMaxPacketSize %u",
315 				ep_desc->bEndpointAddress, ep_desc->wMaxPacketSize);
316 
317 			if (if_desc != NULL && if_desc->bAlternateSetting == 0) {
318 				assign_ep_desc_ptr(udev, ep_desc->bEndpointAddress, ep_desc);
319 			}
320 		}
321 
322 		dhp = (void *)((uint8_t *)dhp + dhp->bLength);
323 	}
324 
325 	if (cfg_desc->bNumInterfaces != tmp_nif) {
326 		LOG_ERR("The configuration has an incorrect number of interfaces");
327 		return -EINVAL;
328 	}
329 
330 	return 0;
331 }
332 
reset_configuration(struct usb_device * const udev)333 static void reset_configuration(struct usb_device *const udev)
334 {
335 	/* Reset all endpoint pointers */
336 	memset(udev->ep_in, 0, sizeof(udev->ep_in));
337 	memset(udev->ep_out, 0, sizeof(udev->ep_out));
338 
339 	/* Reset all interface pointers */
340 	memset(udev->ifaces, 0, sizeof(udev->ifaces));
341 
342 	udev->actual_cfg = 0;
343 	udev->state = USB_STATE_ADDRESSED;
344 }
345 
usbh_device_set_configuration(struct usb_device * const udev,const uint8_t num)346 int usbh_device_set_configuration(struct usb_device *const udev, const uint8_t num)
347 {
348 	struct usb_cfg_descriptor cfg_desc;
349 	uint8_t idx;
350 	int err;
351 
352 	err = k_mutex_lock(&udev->mutex, K_NO_WAIT);
353 	if (err) {
354 		LOG_ERR("Failed to lock USB device");
355 		return err;
356 	}
357 
358 	if (udev->actual_cfg == num) {
359 		LOG_INF("Already active device configuration");
360 		goto error;
361 	}
362 
363 	if (num == 0) {
364 		reset_configuration(udev);
365 		err = usbh_req_set_cfg(udev, num);
366 		if (err) {
367 			LOG_ERR("Set Configuration %u request failed", num);
368 		}
369 
370 		goto error;
371 	}
372 
373 	idx = num - 1;
374 
375 	err = usbh_req_desc_cfg(udev, idx, sizeof(cfg_desc), &cfg_desc);
376 	if (err) {
377 		LOG_ERR("Failed to read configuration %u descriptor", num);
378 		goto error;
379 	}
380 
381 	if (cfg_desc.bDescriptorType != USB_DESC_CONFIGURATION) {
382 		LOG_ERR("Failed to read configuration descriptor");
383 		err = -EINVAL;
384 		goto error;
385 	}
386 
387 	if (cfg_desc.bNumInterfaces == 0) {
388 		LOG_ERR("Configuration %u has no interfaces", cfg_desc.bNumInterfaces);
389 		err = -EINVAL;
390 		goto error;
391 	}
392 
393 	if (cfg_desc.bNumInterfaces >= UHC_INTERFACES_MAX) {
394 		LOG_ERR("Unsupported number of interfaces");
395 		err = -EINVAL;
396 		goto error;
397 	}
398 
399 	udev->cfg_desc = k_heap_alloc(&usb_device_heap,
400 				      cfg_desc.wTotalLength,
401 				      K_NO_WAIT);
402 	if (udev->cfg_desc == NULL) {
403 		LOG_ERR("Failed to allocate memory for configuration descriptor");
404 		err = -ENOMEM;
405 		goto error;
406 	}
407 
408 	err = usbh_req_set_cfg(udev, num);
409 	if (err) {
410 		LOG_ERR("Set Configuration %u request failed", num);
411 		goto error;
412 	}
413 
414 	memset(udev->cfg_desc, 0, cfg_desc.wTotalLength);
415 	if (udev->state == USB_STATE_CONFIGURED) {
416 		reset_configuration(udev);
417 	}
418 
419 	err = usbh_req_desc_cfg(udev, idx, cfg_desc.wTotalLength, udev->cfg_desc);
420 	if (err) {
421 		LOG_ERR("Failed to read configuration descriptor");
422 		k_heap_free(&usb_device_heap, udev->cfg_desc);
423 		goto error;
424 	}
425 
426 	if (memcmp(udev->cfg_desc, &cfg_desc, sizeof(cfg_desc))) {
427 		LOG_ERR("Configuration descriptor read mismatch");
428 		k_heap_free(&usb_device_heap, udev->cfg_desc);
429 		goto error;
430 	}
431 
432 	LOG_INF("Configuration %u bNumInterfaces %u",
433 		cfg_desc.bConfigurationValue, cfg_desc.bNumInterfaces);
434 
435 	err = parse_configuration_descriptor(udev);
436 	if (err) {
437 		k_heap_free(&usb_device_heap, udev->cfg_desc);
438 		goto error;
439 	}
440 
441 	udev->actual_cfg = num;
442 	udev->state = USB_STATE_CONFIGURED;
443 
444 error:
445 	k_mutex_unlock(&udev->mutex);
446 
447 	return err;
448 }
449 
usbh_device_init(struct usb_device * const udev)450 int usbh_device_init(struct usb_device *const udev)
451 {
452 	struct usbh_contex *const uhs_ctx = udev->ctx;
453 	uint8_t new_addr;
454 	int err;
455 
456 	if (udev->state != USB_STATE_DEFAULT) {
457 		LOG_ERR("USB device is not in default state");
458 		return -EALREADY;
459 	}
460 
461 	err = k_mutex_lock(&udev->mutex, K_NO_WAIT);
462 	if (err) {
463 		LOG_ERR("Failed to lock USB device");
464 		return err;
465 	}
466 
467 	/* FIXME: The port to which the device is connected should be reset. */
468 	err = uhc_bus_reset(uhs_ctx->dev);
469 	if (err) {
470 		LOG_ERR("Failed to signal bus reset");
471 		return err;
472 	}
473 
474 	/*
475 	 * Limit mps0 to the minimum supported by full-speed devices until the
476 	 * device descriptor is read.
477 	 */
478 	udev->dev_desc.bMaxPacketSize0 = 8;
479 	err = usbh_req_desc_dev(udev, 8, &udev->dev_desc);
480 	if (err) {
481 		LOG_ERR("Failed to read device descriptor");
482 		goto error;
483 	}
484 
485 	err = validate_device_mps0(udev);
486 	if (err) {
487 		goto error;
488 	}
489 
490 	err = usbh_req_desc_dev(udev, sizeof(udev->dev_desc), &udev->dev_desc);
491 	if (err) {
492 		LOG_ERR("Failed to read device descriptor");
493 		goto error;
494 	}
495 
496 	if (!udev->dev_desc.bNumConfigurations) {
497 		LOG_ERR("Device has no configurations, bNumConfigurations %d",
498 			udev->dev_desc.bNumConfigurations);
499 		goto error;
500 	}
501 
502 	err = alloc_device_address(udev, &new_addr);
503 	if (err) {
504 		LOG_ERR("Failed to allocate device address");
505 		goto error;
506 	}
507 
508 	err = usbh_req_set_address(udev, new_addr);
509 	if (err) {
510 		LOG_ERR("Failed to set device address");
511 		udev->addr = 0;
512 
513 		goto error;
514 	}
515 
516 	udev->addr = new_addr;
517 	udev->state = USB_STATE_ADDRESSED;
518 
519 	LOG_INF("New device with address %u state %u", udev->addr, udev->state);
520 
521 	err = usbh_device_set_configuration(udev, 1);
522 	if (err) {
523 		LOG_ERR("Failed to configure new device with address %u", udev->addr);
524 	}
525 
526 error:
527 	k_mutex_unlock(&udev->mutex);
528 
529 	return err;
530 }
531