Line data Source code
1 1 : /*
2 : * Copyright (c) 2022 Nordic Semiconductor ASA
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @brief USB host controller (UHC) driver API
10 : */
11 :
12 : #ifndef ZEPHYR_INCLUDE_UHC_H
13 : #define ZEPHYR_INCLUDE_UHC_H
14 :
15 : #include <zephyr/kernel.h>
16 : #include <zephyr/device.h>
17 : #include <zephyr/net_buf.h>
18 : #include <zephyr/usb/usb_ch9.h>
19 : #include <zephyr/sys/dlist.h>
20 :
21 : /**
22 : * @brief USB host controller (UHC) driver API
23 : * @defgroup uhc_api USB Host Controller
24 : * @ingroup usb_interfaces
25 : * @since 3.3
26 : * @version 0.1.1
27 : * @{
28 : */
29 :
30 : /** USB device state */
31 0 : enum usb_device_state {
32 : USB_STATE_NOTCONNECTED,
33 : USB_STATE_DEFAULT,
34 : USB_STATE_ADDRESSED,
35 : USB_STATE_CONFIGURED,
36 : };
37 :
38 : /**
39 : * @brief USB device operating speed
40 : */
41 1 : enum usb_device_speed {
42 : /** Device is probably not connected */
43 : USB_SPEED_UNKNOWN,
44 : /** Low speed */
45 : USB_SPEED_SPEED_LS,
46 : /** Full speed */
47 : USB_SPEED_SPEED_FS,
48 : /** High speed */
49 : USB_SPEED_SPEED_HS,
50 : /** Super speed */
51 : USB_SPEED_SPEED_SS,
52 : };
53 :
54 0 : #define UHC_INTERFACES_MAX 32
55 :
56 0 : struct usb_host_interface {
57 0 : struct usb_desc_header *dhp;
58 0 : uint8_t alternate;
59 : };
60 :
61 0 : struct usb_host_ep {
62 0 : struct usb_ep_descriptor *desc;
63 : };
64 :
65 : /**
66 : * Host representation of a USB device
67 : */
68 1 : struct usb_device {
69 : /** dlist node */
70 1 : sys_dnode_t node;
71 : /** An opaque pointer to the host context to which this device belongs */
72 1 : void *ctx;
73 : /** Device mutex */
74 1 : struct k_mutex mutex;
75 : /** USB device descriptor */
76 1 : struct usb_device_descriptor dev_desc;
77 : /** Device state */
78 1 : enum usb_device_state state;
79 : /** Device speed */
80 1 : enum usb_device_speed speed;
81 : /** Actual active device configuration */
82 1 : uint8_t actual_cfg;
83 : /** Device address */
84 1 : uint8_t addr;
85 : /** Pointer to actual device configuration descriptor */
86 1 : void *cfg_desc;
87 : /** Pointers to device interfaces */
88 1 : struct usb_host_interface ifaces[UHC_INTERFACES_MAX + 1];
89 : /** Pointers to device OUT endpoints */
90 1 : struct usb_host_ep ep_out[16];
91 : /** Pointers to device IN endpoints */
92 1 : struct usb_host_ep ep_in[16];
93 : };
94 :
95 : /**
96 : * @brief USB control transfer stage
97 : */
98 0 : enum uhc_control_stage {
99 : UHC_CONTROL_STAGE_SETUP = 0,
100 : UHC_CONTROL_STAGE_DATA,
101 : UHC_CONTROL_STAGE_STATUS,
102 : };
103 :
104 : /**
105 : * UHC endpoint buffer info
106 : *
107 : * This structure is mandatory for all UHC request.
108 : * It contains the meta data about the request and FIFOs
109 : * to store net_buf structures for each request.
110 : *
111 : * The members of this structure should not be used
112 : * directly by a higher layer (host stack).
113 : */
114 1 : struct uhc_transfer {
115 : /** dlist node */
116 1 : sys_dnode_t node;
117 : /** Control transfer setup packet */
118 1 : uint8_t setup_pkt[8];
119 : /** Transfer data buffer */
120 1 : struct net_buf *buf;
121 : /** Endpoint to which request is associated */
122 1 : uint8_t ep;
123 : /** Maximum packet size */
124 1 : uint16_t mps;
125 : /** Interval, used for periodic transfers only */
126 1 : uint16_t interval;
127 : /** Start frame, used for periodic transfers only */
128 1 : uint16_t start_frame;
129 : /** Flag marks request buffer is queued */
130 1 : unsigned int queued : 1;
131 : /** Control stage status, up to the driver to use it or not */
132 1 : unsigned int stage : 2;
133 : /**
134 : * The status stage of the control transfer will be omitted.
135 : * This flag is optional and is mainly used for testing.
136 : */
137 1 : unsigned int no_status : 1;
138 : /** Pointer to USB device */
139 1 : struct usb_device *udev;
140 : /** Pointer to transfer completion callback (opaque for the UHC) */
141 1 : void *cb;
142 : /** Pointer to completion callback private data */
143 1 : void *priv;
144 : /** Transfer result, 0 on success, other values on error */
145 1 : int err;
146 : };
147 :
148 : /**
149 : * @brief USB host controller event types
150 : */
151 1 : enum uhc_event_type {
152 : /** Low speed device connected */
153 : UHC_EVT_DEV_CONNECTED_LS,
154 : /** Full speed device connected */
155 : UHC_EVT_DEV_CONNECTED_FS,
156 : /** High speed device connected */
157 : UHC_EVT_DEV_CONNECTED_HS,
158 : /** Device (peripheral) removed */
159 : UHC_EVT_DEV_REMOVED,
160 : /** Bus reset operation finished */
161 : UHC_EVT_RESETED,
162 : /** Bus suspend operation finished */
163 : UHC_EVT_SUSPENDED,
164 : /** Bus resume operation finished */
165 : UHC_EVT_RESUMED,
166 : /** Remote wakeup signal */
167 : UHC_EVT_RWUP,
168 : /** Endpoint request result event */
169 : UHC_EVT_EP_REQUEST,
170 : /**
171 : * Non-correctable error event, requires attention from higher
172 : * levels or application.
173 : */
174 : UHC_EVT_ERROR,
175 : };
176 :
177 : /**
178 : * USB host controller event
179 : *
180 : * Common structure for all events that originate from
181 : * the UHC driver and are passed to higher layer using
182 : * message queue and a callback (uhc_event_cb_t) provided
183 : * by higher layer during controller initialization (uhc_init).
184 : */
185 1 : struct uhc_event {
186 : /** slist node for the message queue */
187 1 : sys_snode_t node;
188 : /** Event type */
189 1 : enum uhc_event_type type;
190 : union {
191 : /** Event status value, if any */
192 1 : int status;
193 : /** Pointer to request used only for UHC_EVT_EP_REQUEST */
194 1 : struct uhc_transfer *xfer;
195 0 : };
196 : /** Pointer to controller's device struct */
197 1 : const struct device *dev;
198 : };
199 :
200 : /**
201 : * @typedef uhc_event_cb_t
202 : * @brief Callback to submit UHC event to higher layer.
203 : *
204 : * At the higher level, the event is to be inserted into a message queue.
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 1 : typedef int (*uhc_event_cb_t)(const struct device *dev,
212 : const struct uhc_event *const event);
213 :
214 : /**
215 : * USB host controller capabilities
216 : *
217 : * This structure is mainly intended for the USB host stack.
218 : */
219 1 : struct uhc_device_caps {
220 : /** USB high speed capable controller */
221 1 : uint32_t hs : 1;
222 : };
223 :
224 : /**
225 : * Controller is initialized by uhc_init()
226 : */
227 1 : #define UHC_STATUS_INITIALIZED 0
228 : /**
229 : * Controller is enabled and all API functions are available
230 : */
231 1 : #define UHC_STATUS_ENABLED 1
232 :
233 : /**
234 : * Common UHC driver data structure
235 : *
236 : * Mandatory structure for each UHC controller driver.
237 : * To be implemented as device's private data (device->data).
238 : */
239 1 : struct uhc_data {
240 : /** Controller capabilities */
241 1 : struct uhc_device_caps caps;
242 : /** Driver access mutex */
243 1 : struct k_mutex mutex;
244 : /** dlist for control transfers */
245 1 : sys_dlist_t ctrl_xfers;
246 : /** dlist for bulk transfers */
247 1 : sys_dlist_t bulk_xfers;
248 : /** Callback to submit an UHC event to upper layer */
249 1 : uhc_event_cb_t event_cb;
250 : /** Opaque pointer to store higher layer context */
251 1 : const void *event_ctx;
252 : /** USB host controller status */
253 1 : atomic_t status;
254 : /** Driver private data */
255 1 : void *priv;
256 : };
257 :
258 : /**
259 : * @brief Checks whether the controller is initialized.
260 : *
261 : * @param[in] dev Pointer to device struct of the driver instance
262 : *
263 : * @return true if controller is initialized, false otherwise
264 : */
265 1 : static inline bool uhc_is_initialized(const struct device *dev)
266 : {
267 : struct uhc_data *data = dev->data;
268 :
269 : return atomic_test_bit(&data->status, UHC_STATUS_INITIALIZED);
270 : }
271 :
272 : /**
273 : * @brief Checks whether the controller is enabled.
274 : *
275 : * @param[in] dev Pointer to device struct of the driver instance
276 : *
277 : * @return true if controller is enabled, false otherwise
278 : */
279 1 : static inline bool uhc_is_enabled(const struct device *dev)
280 : {
281 : struct uhc_data *data = dev->data;
282 :
283 : return atomic_test_bit(&data->status, UHC_STATUS_ENABLED);
284 : }
285 :
286 : /**
287 : * @cond INTERNAL_HIDDEN
288 : */
289 : struct uhc_api {
290 : int (*lock)(const struct device *dev);
291 : int (*unlock)(const struct device *dev);
292 :
293 : int (*init)(const struct device *dev);
294 : int (*enable)(const struct device *dev);
295 : int (*disable)(const struct device *dev);
296 : int (*shutdown)(const struct device *dev);
297 :
298 : int (*bus_reset)(const struct device *dev);
299 : int (*sof_enable)(const struct device *dev);
300 : int (*bus_suspend)(const struct device *dev);
301 : int (*bus_resume)(const struct device *dev);
302 :
303 : int (*ep_enqueue)(const struct device *dev,
304 : struct uhc_transfer *const xfer);
305 : int (*ep_dequeue)(const struct device *dev,
306 : struct uhc_transfer *const xfer);
307 : };
308 : /**
309 : * @endcond
310 : */
311 :
312 : /**
313 : * @brief Reset USB bus
314 : *
315 : * Perform USB bus reset, controller may emit UHC_EVT_RESETED
316 : * at the end of reset signaling.
317 : *
318 : * @param[in] dev Pointer to device struct of the driver instance
319 : *
320 : * @return 0 on success, all other values should be treated as error.
321 : * @retval -EBUSY if the controller is already performing a bus operation
322 : */
323 1 : static inline int uhc_bus_reset(const struct device *dev)
324 : {
325 : const struct uhc_api *api = dev->api;
326 : int ret;
327 :
328 : api->lock(dev);
329 : ret = api->bus_reset(dev);
330 : api->unlock(dev);
331 :
332 : return ret;
333 : }
334 :
335 : /**
336 : * @brief Enable Start of Frame generator
337 : *
338 : * Enable SOF generator.
339 : *
340 : * @param[in] dev Pointer to device struct of the driver instance
341 : *
342 : * @return 0 on success, all other values should be treated as error.
343 : * @retval -EALREADY if already enabled
344 : */
345 1 : static inline int uhc_sof_enable(const struct device *dev)
346 : {
347 : const struct uhc_api *api = dev->api;
348 : int ret;
349 :
350 : api->lock(dev);
351 : ret = api->sof_enable(dev);
352 : api->unlock(dev);
353 :
354 : return ret;
355 : }
356 :
357 : /**
358 : * @brief Suspend USB bus
359 : *
360 : * Disable SOF generator and emit UHC_EVT_SUSPENDED event when USB bus
361 : * is suspended.
362 : *
363 : * @param[in] dev Pointer to device struct of the driver instance
364 : *
365 : * @return 0 on success, all other values should be treated as error.
366 : * @retval -EALREADY if already suspended
367 : */
368 1 : static inline int uhc_bus_suspend(const struct device *dev)
369 : {
370 : const struct uhc_api *api = dev->api;
371 : int ret;
372 :
373 : api->lock(dev);
374 : ret = api->bus_suspend(dev);
375 : api->unlock(dev);
376 :
377 : return ret;
378 : }
379 :
380 : /**
381 : * @brief Resume USB bus
382 : *
383 : * Signal resume for at least 20ms, emit UHC_EVT_RESUMED at the end of USB
384 : * bus resume signaling. The SoF generator should subsequently start within 3ms.
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 -EBUSY if the controller is already performing a bus operation
390 : */
391 1 : static inline int uhc_bus_resume(const struct device *dev)
392 : {
393 : const struct uhc_api *api = dev->api;
394 : int ret;
395 :
396 : api->lock(dev);
397 : ret = api->bus_resume(dev);
398 : api->unlock(dev);
399 :
400 : return ret;
401 : }
402 :
403 : /**
404 : * @brief Allocate UHC transfer
405 : *
406 : * Allocate a new transfer from common transfer pool.
407 : * Transfer has no buffer after allocation, but can be allocated
408 : * and added from different pools.
409 : *
410 : * @param[in] dev Pointer to device struct of the driver instance
411 : * @param[in] ep Endpoint address
412 : * @param[in] udev Pointer to USB device
413 : * @param[in] cb Transfer completion callback
414 : * @param[in] cb_priv Completion callback callback private data
415 : *
416 : * @return pointer to allocated transfer or NULL on error.
417 : */
418 1 : struct uhc_transfer *uhc_xfer_alloc(const struct device *dev,
419 : const uint8_t ep,
420 : struct usb_device *const udev,
421 : void *const cb,
422 : void *const cb_priv);
423 :
424 : /**
425 : * @brief Allocate UHC transfer with buffer
426 : *
427 : * Allocate a new transfer from common transfer pool with buffer.
428 : *
429 : * @param[in] dev Pointer to device struct of the driver instance
430 : * @param[in] ep Endpoint address
431 : * @param[in] udev Pointer to USB device
432 : * @param[in] cb Transfer completion callback
433 : * @param[in] cb_priv Completion callback callback private data
434 : * @param[in] size Size of the buffer
435 : *
436 : * @return pointer to allocated transfer or NULL on error.
437 : */
438 1 : struct uhc_transfer *uhc_xfer_alloc_with_buf(const struct device *dev,
439 : const uint8_t ep,
440 : struct usb_device *const udev,
441 : void *const cb,
442 : void *const cb_priv,
443 : size_t size);
444 :
445 : /**
446 : * @brief Free UHC transfer and any buffers
447 : *
448 : * Free any buffers and put the transfer back into the transfer pool.
449 : *
450 : * @param[in] dev Pointer to device struct of the driver instance
451 : * @param[in] xfer Pointer to UHC transfer
452 : *
453 : * @return 0 on success, all other values should be treated as error.
454 : */
455 1 : int uhc_xfer_free(const struct device *dev,
456 : struct uhc_transfer *const xfer);
457 :
458 : /**
459 : * @brief Add UHC transfer buffer
460 : *
461 : * Add a previously allocated buffer to the transfer.
462 : *
463 : * @param[in] dev Pointer to device struct of the driver instance
464 : * @param[in] xfer Pointer to UHC transfer
465 : * @param[in] buf Pointer to UHC request buffer
466 : *
467 : * @return pointer to allocated request or NULL on error.
468 : */
469 1 : int uhc_xfer_buf_add(const struct device *dev,
470 : struct uhc_transfer *const xfer,
471 : struct net_buf *buf);
472 : /**
473 : * @brief Allocate UHC transfer buffer
474 : *
475 : * Allocate a new buffer from common request buffer pool and
476 : * assign it to the transfer if the xfer parameter is not NULL.
477 : *
478 : * @param[in] dev Pointer to device struct of the driver instance
479 : * @param[in] size Size of the request buffer
480 : *
481 : * @return pointer to allocated request or NULL on error.
482 : */
483 1 : struct net_buf *uhc_xfer_buf_alloc(const struct device *dev,
484 : const size_t size);
485 :
486 : /**
487 : * @brief Free UHC request buffer
488 : *
489 : * Put the buffer back into the request buffer pool.
490 : *
491 : * @param[in] dev Pointer to device struct of the driver instance
492 : * @param[in] buf Pointer to UHC request buffer
493 : */
494 1 : void uhc_xfer_buf_free(const struct device *dev, struct net_buf *const buf);
495 :
496 : /**
497 : * @brief Queue USB host controller transfer
498 : *
499 : * Add transfer to the queue. If the queue is empty, the transfer
500 : * can be claimed by the controller immediately.
501 : *
502 : * @param[in] dev Pointer to device struct of the driver instance
503 : * @param[in] xfer Pointer to UHC transfer
504 : *
505 : * @return 0 on success, all other values should be treated as error.
506 : * @retval -EPERM controller is not initialized
507 : */
508 1 : int uhc_ep_enqueue(const struct device *dev, struct uhc_transfer *const xfer);
509 :
510 : /**
511 : * @brief Remove a USB host controller transfers from queue
512 : *
513 : * Not implemented yet.
514 : *
515 : * @param[in] dev Pointer to device struct of the driver instance
516 : * @param[in] xfer Pointer to UHC transfer
517 : *
518 : * @return 0 on success, all other values should be treated as error.
519 : * @retval -EPERM controller is not initialized
520 : */
521 1 : int uhc_ep_dequeue(const struct device *dev, struct uhc_transfer *const xfer);
522 :
523 : /**
524 : * @brief Initialize USB host controller
525 : *
526 : * Initialize USB host controller.
527 : *
528 : * @param[in] dev Pointer to device struct of the driver instance
529 : * @param[in] event_cb Event callback from the higher layer (USB host stack)
530 : * @param[in] event_ctx Opaque pointer to higher layer context
531 : *
532 : * @return 0 on success, all other values should be treated as error.
533 : * @retval -EINVAL on parameter error (no callback is passed)
534 : * @retval -EALREADY already initialized
535 : */
536 1 : int uhc_init(const struct device *dev,
537 : uhc_event_cb_t event_cb, const void *const event_ctx);
538 :
539 : /**
540 : * @brief Enable USB host controller
541 : *
542 : * Enable powered USB host controller and allow host stack to
543 : * recognize and enumerate devices.
544 : *
545 : * @param[in] dev Pointer to device struct of the driver instance
546 : *
547 : * @return 0 on success, all other values should be treated as error.
548 : * @retval -EPERM controller is not initialized
549 : * @retval -EALREADY already enabled
550 : */
551 1 : int uhc_enable(const struct device *dev);
552 :
553 : /**
554 : * @brief Disable USB host controller
555 : *
556 : * Disable enabled USB host controller.
557 : *
558 : * @param[in] dev Pointer to device struct of the driver instance
559 : *
560 : * @return 0 on success, all other values should be treated as error.
561 : * @retval -EALREADY already disabled
562 : */
563 1 : int uhc_disable(const struct device *dev);
564 :
565 : /**
566 : * @brief Poweroff USB host controller
567 : *
568 : * Shut down the controller completely to reduce energy consumption
569 : * or to change the role of the controller.
570 : *
571 : * @param[in] dev Pointer to device struct of the driver instance
572 : *
573 : * @return 0 on success, all other values should be treated as error.
574 : * @retval -EALREADY controller is already uninitialized
575 : */
576 1 : int uhc_shutdown(const struct device *dev);
577 :
578 : /**
579 : * @brief Get USB host controller capabilities
580 : *
581 : * Obtain the capabilities of the controller
582 : * such as high speed (HS), and more.
583 : *
584 : * @param[in] dev Pointer to device struct of the driver instance
585 : *
586 : * @return USB host controller capabilities.
587 : */
588 1 : static inline struct uhc_device_caps uhc_caps(const struct device *dev)
589 : {
590 : struct uhc_data *data = dev->data;
591 :
592 : return data->caps;
593 : }
594 :
595 : /**
596 : * @brief Get pointer to higher layer context
597 : *
598 : * The address of the context is passed as an argument to the uhc_init()
599 : * function and is stored in the uhc data.
600 : *
601 : * @param[in] dev Pointer to device struct of the driver instance
602 : *
603 : * @return Opaque pointer to higher layer context
604 : */
605 1 : static inline const void *uhc_get_event_ctx(const struct device *dev)
606 : {
607 : struct uhc_data *data = dev->data;
608 :
609 : return data->event_ctx;
610 : }
611 :
612 : /**
613 : * @}
614 : */
615 :
616 : #endif /* ZEPHYR_INCLUDE_UHC_H */
|