For the simple events, do not check whether the device driver and stack
are marked as initialized. USB device notification will reschedule
delivery if the stack is not yet marked initialized.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Add missing break inside switch statement to allow UDC context to
indicate that current operating speed is High-Speed. Due to missing
break statement, the stack always assumed Full-Speed.
Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
For the last dozen commits, the role of usbd_class_node has actually
been taken over by usbd_class_iter. After cleaning up and merging
usbd_class_node and usbd_class_data, we can rename usbd_class_iter to
usbd_class_node to better reflect its role.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Since only usbd_class_node contains the class instance data, rename it
to usbd_class_data.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
USB High-Speed devices must be able to operate at both High-Speed and
Full-Speed. The USB specification allows the device to have different
configurations depending on connection speed. Modify the API to reflect
USB Specification requirements on what can (e.g. configurations) and
what cannot (e.g. VID, PID) be speed dependent.
While the class configurations for different speeds are completely
independent, the actual class instances are shared between operating
speeds (because only one speed can be active at a time). Classes are
free to provide different number of interfaces and/or endpoints for
different speeds. The endpoints are assigned for all operating speeds
during initialization.
Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
Introduce usbd_class_iter for keeping endpoint assignment variables
and the single-linked list node. No functional changes right now, but
this paves the way for independent speed specific configurations.
Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
Save actual device speed in the device context and add helpers to get
highest supported and actual speed.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
The implementation uses the system workqueue and a callback provided
and registered by the application. The application callback is called in
the context of the workqueue. Notification messages are stored in a
queue and delivered to the callback in sequence.
We cannot call application callback directly from the USB device stack
thread because the behavior of arbitrary code provided by the
application is unpredictable, and we do not want it to be executed in
the same context where all events from the device controller are
handled.
Nor can we use the ZBUS subsystem directly. ZBUS offloads responsibility
for defined behavior to the observers and application, and does not
provide any way for the publisher to enforce defined behavior and
execution context.
ZBUS listener would be called from the USB thread context and is not
acceptable. ZBUS subscriber does not provide delivery guarantee and
cached message can be overwritten. ZBUS message subscriber has
cumbersome global configuration and buffers that are too complicated to
handle from USB configuration, and even if we would use it, defined
behavior is not possible because of how listener and subscriber are
handled.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Start of Frame is not relevant for most classes, but it is crucial for
isochronous operation. The most prominent example where SOF is necessary
is USB Audio class.
Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
With gcc from the zephyr sdk and -Wold-style-declaration is giving this
output:
zephyr/arch/arm/core/aarch32/cortex_a_r/fault.c:101:1: warning:
'inline' is not at beginning of declaration [-Wold-style-declaration]
101 | static void ALWAYS_INLINE
z_arm_fpu_caller_save(struct __fpu_sf *fpu)
| ^~~~~~
I searched to all of the source code to find these further occurances
where inline is not at the beginning of a function declaration.
Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
There may be more than one context using the same device, for example,
if the shell module is enabled. Check if another context that uses
the same device is initialized.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
At the shutdown of USB device stack we have to cleanup and
remove all registered class instances and string descriptors
from a configuration.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Until now iterable sections APIs have been part of the toolchain
(common) headers. They are not strictly related to a toolchain, they
just rely on linker providing support for sections. Most files relied on
indirect includes to access the API, now, it is included as needed.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The init infrastructure, found in `init.h`, is currently used by:
- `SYS_INIT`: to call functions before `main`
- `DEVICE_*`: to initialize devices
They are all sorted according to an initialization level + a priority.
`SYS_INIT` calls are really orthogonal to devices, however, the required
function signature requires a `const struct device *dev` as a first
argument. The only reason for that is because the same init machinery is
used by devices, so we have something like:
```c
struct init_entry {
int (*init)(const struct device *dev);
/* only set by DEVICE_*, otherwise NULL */
const struct device *dev;
}
```
As a result, we end up with such weird/ugly pattern:
```c
static int my_init(const struct device *dev)
{
/* always NULL! add ARG_UNUSED to avoid compiler warning */
ARG_UNUSED(dev);
...
}
```
This is really a result of poor internals isolation. This patch proposes
a to make init entries more flexible so that they can accept sytem
initialization calls like this:
```c
static int my_init(void)
{
...
}
```
This is achieved using a union:
```c
union init_function {
/* for SYS_INIT, used when init_entry.dev == NULL */
int (*sys)(void);
/* for DEVICE*, used when init_entry.dev != NULL */
int (*dev)(const struct device *dev);
};
struct init_entry {
/* stores init function (either for SYS_INIT or DEVICE*)
union init_function init_fn;
/* stores device pointer for DEVICE*, NULL for SYS_INIT. Allows
* to know which union entry to call.
*/
const struct device *dev;
}
```
This solution **does not increase ROM usage**, and allows to offer clean
public APIs for both SYS_INIT and DEVICE*. Note that however, init
machinery keeps a coupling with devices.
**NOTE**: This is a breaking change! All `SYS_INIT` functions will need
to be converted to the new signature. See the script offered in the
following commit.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
init: convert SYS_INIT functions to the new signature
Conversion scripted using scripts/utils/migrate_sys_init.py.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
manifest: update projects for SYS_INIT changes
Update modules with updated SYS_INIT calls:
- hal_ti
- lvgl
- sof
- TraceRecorderSource
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: devicetree: devices: adjust test
Adjust test according to the recently introduced SYS_INIT
infrastructure.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: kernel: threads: adjust SYS_INIT call
Adjust to the new signature: int (*init_fn)(void);
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This allows us to get the result of synchronous transfer without
any hacks, just from the net_buf structure.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
The device supprt brings support for multiple stack instances,
multiple configuration, asynchronous transfer model, ability to
change most of the properties of a device at runtime and
the composition of configuration and classes at runtime.
The stack requires new UDC driver API and is not compatible
with old driver API (usb_dc_). The classes (functions) of old
(current) USB device stack cannot be used with new ones and must
be ported.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>