1 /*
2 * Copyright (c) 2021-2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief New USB device controller (UDC) driver API
10 */
11
12 #ifndef ZEPHYR_INCLUDE_UDC_H
13 #define ZEPHYR_INCLUDE_UDC_H
14
15 #include <zephyr/kernel.h>
16 #include <zephyr/device.h>
17 #include <zephyr/drivers/usb/udc_buf.h>
18 #include <zephyr/sys/atomic.h>
19 #include <zephyr/usb/usb_ch9.h>
20
21 /**
22 * @brief Maximum packet size of control endpoint supported by the controller.
23 */
24 enum udc_mps0 {
25 UDC_MPS0_8,
26 UDC_MPS0_16,
27 UDC_MPS0_32,
28 UDC_MPS0_64,
29 };
30
31 /**
32 * USB device controller capabilities
33 *
34 * This structure is mainly intended for the USB device stack.
35 */
36 struct udc_device_caps {
37 /** USB high speed capable controller */
38 uint32_t hs : 1;
39 /** Controller supports USB remote wakeup */
40 uint32_t rwup : 1;
41 /** Controller performs status OUT stage automatically */
42 uint32_t out_ack : 1;
43 /** Controller expects device address to be set before status stage */
44 uint32_t addr_before_status : 1;
45 /** Controller can detect the state change of USB supply VBUS.*/
46 uint32_t can_detect_vbus : 1;
47 /** Maximum packet size for control endpoint */
48 enum udc_mps0 mps0 : 2;
49 };
50
51 /**
52 * @brief USB device actual speed
53 */
54 enum udc_bus_speed {
55 /** Device is probably not connected */
56 UDC_BUS_UNKNOWN,
57 /** Device is connected to a full speed bus */
58 UDC_BUS_SPEED_FS,
59 /** Device is connected to a high speed bus */
60 UDC_BUS_SPEED_HS,
61 /** Device is connected to a super speed bus */
62 UDC_BUS_SPEED_SS,
63 };
64
65 /**
66 * USB device controller endpoint capabilities
67 */
68 struct udc_ep_caps {
69 /** Maximum packet size of the endpoint buffer */
70 uint32_t mps : 16;
71 /** Control transfer capable endpoint (for completeness) */
72 uint32_t control : 1;
73 /** Interrupt transfer capable endpoint */
74 uint32_t interrupt : 1;
75 /** Bulk transfer capable endpoint */
76 uint32_t bulk : 1;
77 /** ISO transfer capable endpoint */
78 uint32_t iso : 1;
79 /** High-Bandwidth (interrupt or iso) capable endpoint */
80 uint32_t high_bandwidth : 1;
81 /** IN transfer capable endpoint */
82 uint32_t in : 1;
83 /** OUT transfer capable endpoint */
84 uint32_t out : 1;
85 };
86
87 /**
88 * USB device controller endpoint status
89 */
90 struct udc_ep_stat {
91 /** Endpoint is enabled */
92 uint32_t enabled : 1;
93 /** Endpoint is halted (returning STALL PID) */
94 uint32_t halted : 1;
95 /** Last submitted PID is DATA1 */
96 uint32_t data1 : 1;
97 /** If double buffering is supported, last used buffer is odd */
98 uint32_t odd : 1;
99 /** Endpoint is busy */
100 uint32_t busy : 1;
101 };
102
103 /**
104 * USB device controller endpoint configuration
105 *
106 * This structure is mandatory for configuration and management of endpoints.
107 * It is not exposed to higher layer and is used only by internal part
108 * of UDC API and driver.
109 */
110 struct udc_ep_config {
111 /** Endpoint requests FIFO */
112 struct k_fifo fifo;
113 /** Endpoint capabilities */
114 struct udc_ep_caps caps;
115 /** Endpoint status */
116 struct udc_ep_stat stat;
117 /** Endpoint address */
118 uint8_t addr;
119 /** Endpoint attributes */
120 uint8_t attributes;
121 /** Maximum packet size */
122 uint16_t mps;
123 /** Polling interval */
124 uint8_t interval;
125 };
126
127
128 /**
129 * @brief USB device controller event types
130 */
131 enum udc_event_type {
132 /** VBUS ready event. Signals that VBUS is in stable condition. */
133 UDC_EVT_VBUS_READY,
134 /** VBUS removed event. Signals that VBUS is below the valid range. */
135 UDC_EVT_VBUS_REMOVED,
136 /** Device resume event */
137 UDC_EVT_RESUME,
138 /** Device suspended event */
139 UDC_EVT_SUSPEND,
140 /** Port reset detected */
141 UDC_EVT_RESET,
142 /** Start of Frame event */
143 UDC_EVT_SOF,
144 /** Endpoint request result event */
145 UDC_EVT_EP_REQUEST,
146 /**
147 * Non-correctable error event, requires attention from higher
148 * levels or application.
149 */
150 UDC_EVT_ERROR,
151 };
152
153 /**
154 * USB device controller event
155 *
156 * Common structure for all events that originate from
157 * the UDC driver and are passed to higher layer using
158 * message queue and a callback (udc_event_cb_t) provided
159 * by higher layer during controller initialization (udc_init).
160 */
161 struct udc_event {
162 /** Event type */
163 enum udc_event_type type;
164 union {
165 /** Event value */
166 uint32_t value;
167 /** Event status value, if any */
168 int status;
169 /** Pointer to request used only for UDC_EVT_EP_REQUEST */
170 struct net_buf *buf;
171 };
172 /** Pointer to device struct */
173 const struct device *dev;
174 };
175
176 /**
177 * UDC endpoint buffer info
178 *
179 * This structure is mandatory for all UDC request.
180 * It contains the meta data about the request and is stored in
181 * user_data array of net_buf structure for each request.
182 */
183 struct udc_buf_info {
184 /** Endpoint to which request is associated */
185 uint8_t ep;
186 /** Flag marks setup transfer */
187 unsigned int setup : 1;
188 /** Flag marks data stage of setup transfer */
189 unsigned int data : 1;
190 /** Flag marks status stage of setup transfer */
191 unsigned int status : 1;
192 /** Flag marks ZLP at the end of a transfer */
193 unsigned int zlp : 1;
194 /** Flag marks request buffer claimed by the controller (TBD) */
195 unsigned int claimed : 1;
196 /** Flag marks request buffer is queued (TBD) */
197 unsigned int queued : 1;
198 /** Transfer owner (usually pointer to a class instance) */
199 void *owner;
200 /** Transfer result, 0 on success, other values on error */
201 int err;
202 } __packed;
203
204 /**
205 * @typedef udc_event_cb_t
206 * @brief Callback to submit UDC event to higher layer.
207 *
208 * At the higher level, the event is to be inserted into a message queue.
209 * (TBD) Maybe it is better to provide a pointer to k_msgq passed during
210 * initialization.
211 *
212 * @param[in] dev Pointer to device struct of the driver instance
213 * @param[in] event Point to event structure
214 *
215 * @return 0 on success, all other values should be treated as error.
216 */
217 typedef int (*udc_event_cb_t)(const struct device *dev,
218 const struct udc_event *const event);
219
220 /**
221 * @brief UDC driver API
222 * This is the mandatory API any USB device controller driver needs to expose
223 * with exception of:
224 * device_speed(), test_mode() are only required for HS controllers
225 */
226 struct udc_api {
227 enum udc_bus_speed (*device_speed)(const struct device *dev);
228 int (*ep_enqueue)(const struct device *dev,
229 struct udc_ep_config *const cfg,
230 struct net_buf *const buf);
231 int (*ep_dequeue)(const struct device *dev,
232 struct udc_ep_config *const cfg);
233 int (*ep_set_halt)(const struct device *dev,
234 struct udc_ep_config *const cfg);
235 int (*ep_clear_halt)(const struct device *dev,
236 struct udc_ep_config *const cfg);
237 int (*ep_try_config)(const struct device *dev,
238 struct udc_ep_config *const cfg);
239 int (*ep_enable)(const struct device *dev,
240 struct udc_ep_config *const cfg);
241 int (*ep_disable)(const struct device *dev,
242 struct udc_ep_config *const cfg);
243 int (*host_wakeup)(const struct device *dev);
244 int (*set_address)(const struct device *dev,
245 const uint8_t addr);
246 int (*test_mode)(const struct device *dev,
247 const uint8_t mode, const bool dryrun);
248 int (*enable)(const struct device *dev);
249 int (*disable)(const struct device *dev);
250 int (*init)(const struct device *dev);
251 int (*shutdown)(const struct device *dev);
252 int (*lock)(const struct device *dev);
253 int (*unlock)(const struct device *dev);
254 };
255
256 /**
257 * Controller is initialized by udc_init() and can generate the VBUS events,
258 * if capable, but shall not be recognizable by host.
259 */
260 #define UDC_STATUS_INITIALIZED 0
261 /**
262 * Controller is enabled and all API functions are available,
263 * controller is recognizable by host.
264 */
265 #define UDC_STATUS_ENABLED 1
266 /** Controller is suspended by the host */
267 #define UDC_STATUS_SUSPENDED 2
268
269 /**
270 * Common UDC driver data structure
271 *
272 * Mandatory structure for each UDC controller driver.
273 * To be implemented as device's private data (device->data).
274 */
275 struct udc_data {
276 /** LUT for endpoint management */
277 struct udc_ep_config *ep_lut[32];
278 /** Controller capabilities */
279 struct udc_device_caps caps;
280 /** Driver access mutex */
281 struct k_mutex mutex;
282 /** Callback to submit an UDC event to higher layer */
283 udc_event_cb_t event_cb;
284 /** Opaque pointer to store higher layer context */
285 const void *event_ctx;
286 /** USB device controller status */
287 atomic_t status;
288 /** Internal used Control Sequence Stage */
289 int stage;
290 /** Pointer to buffer containing setup packet */
291 struct net_buf *setup;
292 /** Driver private data */
293 void *priv;
294 };
295
296 /**
297 * @brief New USB device controller (UDC) driver API
298 * @defgroup udc_api USB device controller driver API
299 * @ingroup io_interfaces
300 * @since 3.3
301 * @version 0.1.0
302 * @{
303 */
304
305 /**
306 * @brief Checks whether the controller is initialized.
307 *
308 * @param[in] dev Pointer to device struct of the driver instance
309 *
310 * @return true if controller is initialized, false otherwise
311 */
udc_is_initialized(const struct device * dev)312 static inline bool udc_is_initialized(const struct device *dev)
313 {
314 struct udc_data *data = dev->data;
315
316 return atomic_test_bit(&data->status, UDC_STATUS_INITIALIZED);
317 }
318
319 /**
320 * @brief Checks whether the controller is enabled.
321 *
322 * @param[in] dev Pointer to device struct of the driver instance
323 *
324 * @return true if controller is enabled, false otherwise
325 */
udc_is_enabled(const struct device * dev)326 static inline bool udc_is_enabled(const struct device *dev)
327 {
328 struct udc_data *data = dev->data;
329
330 return atomic_test_bit(&data->status, UDC_STATUS_ENABLED);
331 }
332
333 /**
334 * @brief Checks whether the controller is suspended.
335 *
336 * @param[in] dev Pointer to device struct of the driver instance
337 *
338 * @return true if controller is suspended, false otherwise
339 */
udc_is_suspended(const struct device * dev)340 static inline bool udc_is_suspended(const struct device *dev)
341 {
342 struct udc_data *data = dev->data;
343
344 return atomic_test_bit(&data->status, UDC_STATUS_SUSPENDED);
345 }
346
347 /**
348 * @brief Initialize USB device controller
349 *
350 * Initialize USB device controller and control IN/OUT endpoint.
351 * After initialization controller driver should be able to detect
352 * power state of the bus and signal power state changes.
353 *
354 * @param[in] dev Pointer to device struct of the driver instance
355 * @param[in] event_cb Event callback from the higher layer (USB device stack)
356 * @param[in] event_ctx Opaque pointer to higher layer context
357 *
358 * @return 0 on success, all other values should be treated as error.
359 * @retval -EINVAL on parameter error (no callback is passed)
360 * @retval -EALREADY already initialized
361 */
362 int udc_init(const struct device *dev,
363 udc_event_cb_t event_cb, const void *const event_ctx);
364
365 /**
366 * @brief Enable USB device controller
367 *
368 * Enable powered USB device controller and allow host to
369 * recognize and enumerate the device.
370 *
371 * @param[in] dev Pointer to device struct of the driver instance
372 *
373 * @return 0 on success, all other values should be treated as error.
374 * @retval -EPERM controller is not initialized
375 * @retval -EALREADY already enabled
376 * @retval -ETIMEDOUT enable operation timed out
377 */
378 int udc_enable(const struct device *dev);
379
380 /**
381 * @brief Disable USB device controller
382 *
383 * Disable enabled USB device controller.
384 * The driver should continue to detect power state changes.
385 *
386 * @param[in] dev Pointer to device struct of the driver instance
387 *
388 * @return 0 on success, all other values should be treated as error.
389 * @retval -EALREADY already disabled
390 */
391 int udc_disable(const struct device *dev);
392
393 /**
394 * @brief Poweroff USB device controller
395 *
396 * Shut down the controller completely to reduce energy consumption
397 * or to change the role of the controller.
398 *
399 * @param[in] dev Pointer to device struct of the driver instance
400 *
401 * @return 0 on success, all other values should be treated as error.
402 * @retval -EALREADY controller is not initialized
403 */
404 int udc_shutdown(const struct device *dev);
405
406 /**
407 * @brief Get USB device controller capabilities
408 *
409 * Obtain the capabilities of the controller
410 * such as full speed (FS), high speed (HS), and more.
411 *
412 * @param[in] dev Pointer to device struct of the driver instance
413 *
414 * @return USB device controller capabilities.
415 */
udc_caps(const struct device * dev)416 static inline struct udc_device_caps udc_caps(const struct device *dev)
417 {
418 struct udc_data *data = dev->data;
419
420 return data->caps;
421 }
422
423 /**
424 * @brief Get actual USB device speed
425 *
426 * The function should be called after the reset event to determine
427 * the actual bus speed.
428 *
429 * @param[in] dev Pointer to device struct of the driver instance
430 *
431 * @return USB device controller capabilities.
432 */
433 enum udc_bus_speed udc_device_speed(const struct device *dev);
434
435 /**
436 * @brief Set USB device address.
437 *
438 * Set address of enabled USB device.
439 *
440 * @param[in] dev Pointer to device struct of the driver instance
441 * @param[in] addr USB device address
442 *
443 * @return 0 on success, all other values should be treated as error.
444 * @retval -EPERM controller is not enabled (or not initialized)
445 */
udc_set_address(const struct device * dev,const uint8_t addr)446 static inline int udc_set_address(const struct device *dev, const uint8_t addr)
447 {
448 const struct udc_api *api = dev->api;
449 int ret;
450
451 if (!udc_is_enabled(dev)) {
452 return -EPERM;
453 }
454
455 api->lock(dev);
456 ret = api->set_address(dev, addr);
457 api->unlock(dev);
458
459 return ret;
460 }
461
462 /**
463 * @brief Enable Test Mode.
464 *
465 * For compliance testing, high-speed controllers must support test modes.
466 * A particular test is enabled by a SetFeature(TEST_MODE) request.
467 * To disable a test mode, device needs to be power cycled.
468 *
469 * @param[in] dev Pointer to device struct of the driver instance
470 * @param[in] mode Test mode
471 * @param[in] dryrun Verify that a particular mode can be enabled, but do not
472 * enable test mode
473 *
474 * @return 0 on success, all other values should be treated as error.
475 * @retval -ENOTSUP Test mode is not supported
476 */
udc_test_mode(const struct device * dev,const uint8_t mode,const bool dryrun)477 static inline int udc_test_mode(const struct device *dev,
478 const uint8_t mode, const bool dryrun)
479 {
480 const struct udc_api *api = dev->api;
481 int ret;
482
483 if (!udc_is_enabled(dev)) {
484 return -EPERM;
485 }
486
487 if (api->test_mode != NULL) {
488 api->lock(dev);
489 ret = api->test_mode(dev, mode, dryrun);
490 api->unlock(dev);
491 } else {
492 ret = -ENOTSUP;
493 }
494
495 return ret;
496 }
497
498 /**
499 * @brief Initiate host wakeup procedure.
500 *
501 * Initiate host wakeup. Only possible when the bus is suspended.
502 *
503 * @param[in] dev Pointer to device struct of the driver instance
504 *
505 * @return 0 on success, all other values should be treated as error.
506 * @retval -EPERM controller is not enabled (or not initialized)
507 */
udc_host_wakeup(const struct device * dev)508 static inline int udc_host_wakeup(const struct device *dev)
509 {
510 const struct udc_api *api = dev->api;
511 int ret;
512
513 if (!udc_is_enabled(dev)) {
514 return -EPERM;
515 }
516
517 api->lock(dev);
518 ret = api->host_wakeup(dev);
519 api->unlock(dev);
520
521 return ret;
522 }
523
524 /**
525 * @brief Try an endpoint configuration.
526 *
527 * Try an endpoint configuration based on endpoint descriptor.
528 * This function may modify wMaxPacketSize descriptor fields
529 * of the endpoint. All properties of the descriptor,
530 * such as direction, and transfer type, should be set correctly.
531 * If wMaxPacketSize value is zero, it will be
532 * updated to maximum buffer size of the endpoint.
533 *
534 * @param[in] dev Pointer to device struct of the driver instance
535 * @param[in] ep Endpoint address (same as bEndpointAddress)
536 * @param[in] attributes Endpoint attributes (same as bmAttributes)
537 * @param[in] mps Maximum packet size (same as wMaxPacketSize)
538 * @param[in] interval Polling interval (same as bInterval)
539 *
540 * @return 0 on success, all other values should be treated as error.
541 * @retval -EINVAL on wrong parameter
542 * @retval -ENOTSUP endpoint configuration not supported
543 * @retval -ENODEV no endpoints available
544 */
545 int udc_ep_try_config(const struct device *dev,
546 const uint8_t ep,
547 const uint8_t attributes,
548 uint16_t *const mps,
549 const uint8_t interval);
550
551 /**
552 * @brief Configure and enable endpoint.
553 *
554 * Configure and make an endpoint ready for use.
555 * Valid for all endpoints except control IN/OUT.
556 *
557 * @param[in] dev Pointer to device struct of the driver instance
558 * @param[in] ep Endpoint address (same as bEndpointAddress)
559 * @param[in] attributes Endpoint attributes (same as bmAttributes)
560 * @param[in] mps Maximum packet size (same as wMaxPacketSize)
561 * @param[in] interval Polling interval (same as bInterval)
562 *
563 * @return 0 on success, all other values should be treated as error.
564 * @retval -EINVAL on wrong parameter (control IN/OUT endpoint)
565 * @retval -EPERM controller is not initialized
566 * @retval -ENODEV endpoint configuration not found
567 * @retval -EALREADY endpoint is already enabled
568 */
569 int udc_ep_enable(const struct device *dev,
570 const uint8_t ep,
571 const uint8_t attributes,
572 const uint16_t mps,
573 const uint8_t interval);
574
575 /**
576 * @brief Disable endpoint.
577 *
578 * Valid for all endpoints except control IN/OUT.
579 *
580 * @param[in] dev Pointer to device struct of the driver instance
581 * @param[in] ep Endpoint address
582 *
583 * @return 0 on success, all other values should be treated as error.
584 * @retval -EINVAL on wrong parameter (control IN/OUT endpoint)
585 * @retval -ENODEV endpoint configuration not found
586 * @retval -EALREADY endpoint is already disabled
587 * @retval -EPERM controller is not initialized
588 */
589 int udc_ep_disable(const struct device *dev, const uint8_t ep);
590
591 /**
592 * @brief Halt endpoint
593 *
594 * Valid for all endpoints.
595 *
596 * @param[in] dev Pointer to device struct of the driver instance
597 * @param[in] ep Endpoint address
598 *
599 * @return 0 on success, all other values should be treated as error.
600 * @retval -ENODEV endpoint configuration not found
601 * @retval -ENOTSUP not supported (e.g. isochronous endpoint)
602 * @retval -EPERM controller is not enabled
603 */
604 int udc_ep_set_halt(const struct device *dev, const uint8_t ep);
605
606 /**
607 * @brief Clear endpoint halt
608 *
609 * Valid for all endpoints.
610 *
611 * @param[in] dev Pointer to device struct of the driver instance
612 * @param[in] ep Endpoint address
613 *
614 * @return 0 on success, all other values should be treated as error.
615 * @retval -ENODEV endpoint configuration not found
616 * @retval -ENOTSUP not supported (e.g. isochronous endpoint)
617 * @retval -EPERM controller is not enabled
618 */
619 int udc_ep_clear_halt(const struct device *dev, const uint8_t ep);
620
621 /**
622 * @brief Queue USB device controller request
623 *
624 * Add request to the queue. If the queue is empty, the request
625 * buffer can be claimed by the controller immediately.
626 *
627 * @param[in] dev Pointer to device struct of the driver instance
628 * @param[in] buf Pointer to UDC request buffer
629 *
630 * @return 0 on success, all other values should be treated as error.
631 * @retval -ENODEV endpoint configuration not found
632 * @retval -EACCES endpoint is not enabled (TBD)
633 * @retval -EBUSY request can not be queued
634 * @retval -EPERM controller is not initialized
635 */
636 int udc_ep_enqueue(const struct device *dev, struct net_buf *const buf);
637
638 /**
639 * @brief Remove all USB device controller requests from endpoint queue
640 *
641 * UDC_EVT_EP_REQUEST event will be generated when the driver
642 * releases claimed buffer, no new requests will be claimed,
643 * all requests in the queue will passed as chained list of
644 * the event variable buf. The endpoint queue is empty after that.
645 *
646 * @param[in] dev Pointer to device struct of the driver instance
647 * @param[in] ep Endpoint address
648 *
649 * @return 0 on success, all other values should be treated as error.
650 * @retval -ENODEV endpoint configuration not found
651 * @retval -EACCES endpoint is not disabled
652 * @retval -EPERM controller is not initialized
653 */
654 int udc_ep_dequeue(const struct device *dev, const uint8_t ep);
655
656 /**
657 * @brief Allocate UDC request buffer
658 *
659 * Allocate a new buffer from common request buffer pool.
660 *
661 * @param[in] dev Pointer to device struct of the driver instance
662 * @param[in] ep Endpoint address
663 * @param[in] size Size of the request buffer
664 *
665 * @return pointer to allocated request or NULL on error.
666 */
667 struct net_buf *udc_ep_buf_alloc(const struct device *dev,
668 const uint8_t ep,
669 const size_t size);
670
671 /**
672 * @brief Free UDC request buffer
673 *
674 * Put the buffer back into the request buffer pool.
675 *
676 * @param[in] dev Pointer to device struct of the driver instance
677 * @param[in] buf Pointer to UDC request buffer
678 *
679 * @return 0 on success, all other values should be treated as error.
680 */
681 int udc_ep_buf_free(const struct device *dev, struct net_buf *const buf);
682
683 /**
684 * @brief Set ZLP flag in requests metadata.
685 *
686 * The controller should send a ZLP at the end of the transfer.
687 *
688 * @param[in] buf Pointer to UDC request buffer
689 */
udc_ep_buf_set_zlp(struct net_buf * const buf)690 static inline void udc_ep_buf_set_zlp(struct net_buf *const buf)
691 {
692 struct udc_buf_info *bi;
693
694 __ASSERT_NO_MSG(buf);
695 bi = (struct udc_buf_info *)net_buf_user_data(buf);
696 if (USB_EP_DIR_IS_IN(bi->ep)) {
697 bi->zlp = 1;
698 }
699 }
700
701 /**
702 * @brief Get requests metadata.
703 *
704 * @param[in] buf Pointer to UDC request buffer
705 *
706 * @return pointer to metadata structure.
707 */
udc_get_buf_info(const struct net_buf * const buf)708 static inline struct udc_buf_info *udc_get_buf_info(const struct net_buf *const buf)
709 {
710 __ASSERT_NO_MSG(buf);
711 return (struct udc_buf_info *)net_buf_user_data(buf);
712 }
713
714
715 /**
716 * @brief Get pointer to higher layer context
717 *
718 * The address of the context is passed as an argument to the udc_init()
719 * function and is stored in the UDC data.
720 *
721 * @param[in] dev Pointer to device struct of the driver instance
722 *
723 * @return Opaque pointer to higher layer context
724 */
udc_get_event_ctx(const struct device * dev)725 static inline const void *udc_get_event_ctx(const struct device *dev)
726 {
727 struct udc_data *data = dev->data;
728
729 return data->event_ctx;
730 }
731
732 /**
733 * @brief Get endpoint size from UDC endpoint configuration
734 *
735 * @param[in] cfg Pointer to UDC endpoint configuration
736 *
737 * @return Endpoint size
738 */
udc_mps_ep_size(const struct udc_ep_config * const cfg)739 static inline uint16_t udc_mps_ep_size(const struct udc_ep_config *const cfg)
740 {
741 return USB_MPS_EP_SIZE(cfg->mps);
742 }
743
744 /**
745 * @}
746 */
747
748 #endif /* ZEPHYR_INCLUDE_UDC_H */
749