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