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