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