1/*
2 * Copyright (c) 2026 Deveritec GmbH.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 *
7 */
8
9/**
10 * @file
11 * @brief Public DECT NR+ Radio Driver API
12 *
13 * @attention This file contains pseudo code for demonstration purposes.
14 * Definitions may be missing and in that case are only place
15 * holders for types representing related objects.
16 */
17
18#ifndef DECTNRP_DRIVER_H_
19#define DECTNRP_DRIVER_H_
20
21#include <net/net_if.h>
22#include <net/net_dev.h>
23#include <net/net_pkt.h>
24#include <net/net_buf.h>
25#include <net/net_time.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31/**
32 * @defgroup dectnrp_driver DECT NR+ Drivers
33 * @version 0.0.1
34 * @ingroup dectnrp
35 *
36 * @brief DECT NR+ driver API
37 *
38 * @details This API provides a common representation of vendor-specific
39 * hardware and firmware to the DECT NR+ L2.
40 * **Application developers should never interface directly with this API.** It
41 * is of interest to driver maintainers only.
42 *
43 * Implementing the basic driver API will ensure integration with the native L2
44 * stack as well as basic support for DECT NR+.
45 *
46 * @note References are to the ETSI TS 103 636 DECTNRP NR+ V2.1.1 (2024-10) standard
47 * If not further noted all references in this file refer to ETSI TS 103 636-4.
48 *
49 * @{
50 */
51
52/**
53 * @brief Flags related to DECTNRP_DRIVER_OP_TX
54 */
55struct dectnrp_tx_mode {
56 uint8_t is_scheduled: 1;
57 uint8_t is_lbt: 1;
58 uint8_t is_harq: 1;
59 uint8_t is_beacon: 1;
60};
61
62/**
63 * @brief Flags related to DECTNRP_DRIVER_OP_RX
64 */
65struct dectnrp_rx_mode {
66 uint8_t is_scheduled: 1;
67 uint8_t is_beacon: 1;
68};
69
70#ifdef CONFIG_DECTNRP_DRIVER_SCHEDULED_API
71
72/**
73 * @brief Enumerates all possible driver operation types.
74 */
75enum dectnrp_driver_op_type {
76 DECTNRP_DRIVER_OP_TX,
77 DECTNRP_DRIVER_OP_RX,
78 DECTNRP_DRIVER_OP_RSSI1,
79};
80
81/**
82 * @brief Descriptor of one driver operation.
83 */
84struct dectnrp_driver_op {
85
86 /** Channel this operation should be scheduled into. */
87 uint16_t channel;
88 /** Start time this operation should be scheduled at in
89 * modem ticks.
90 * To be scheduled immediately if start_time == 0.
91 */
92 net_time_t start_time;
93 /** Operation type. */
94 enum dectnrp_driver_op_type type;
95 union {
96 /** Parameters when type == DECTNRP_DRIVER_OP_TX. */
97 struct {
98 struct dectnrp_tx_mode mode;
99 const void *resource;
100 struct net_pkt *pkt;
101 /** Parameters when mode.is_lbt == true. */
102 struct {
103 uint32_t period;
104 uint8_t rssi_threshold;
105 uint8_t retry_count;
106 } lbt;
107 } tx;
108 /** Parameters when type == DECTNRP_DRIVER_OP_RX. */
109 struct {
110 struct dectnrp_rx_mode mode;
111 const void *resource;
112 uint32_t duration;
113 uint8_t expected_rssi;
114 } rx;
115 /** Parameters when type == DECTNRP_DRIVER_OP_RSSI1. */
116 struct {
117 uint32_t subslots;
118 struct dectnrp_rssi1_result *result;
119 } rssi1;
120 };
121
122 /** Holds the status of this operation. */
123 int status;
124};
125
126/**
127 * @brief Enumerate all events notified via dectnrp_event_cb_t.
128 */
129enum dectnrp_event {
130 /** An operation has been finished */
131 DECTNRP_EVENT_OP_FINISHED,
132 /** Provides RSSI1 results. */
133 DECTNRP_EVENT_OP_RESULTS,
134};
135
136union dectnrp_event_data {
137 union {
138 /** DECTNRP_EVENT_OP_FINISHED */
139 /** DECTNRP_EVENT_OP_RESULTS */
140 struct {
141 struct dectnrp_driver_op *op;
142 } op_finished;
143 };
144};
145
146/** Event callback function */
147typedef void (*dectnrp_event_cb_t)(const struct device *dev, enum dectnrp_event evt,
148 union dectnrp_event_data *event_data);
149
150#endif /* CONFIG_DECTNRP_DRIVER_SCHEDULED_API */
151
152/**
153 * @brief DECTNRP driver interface API.
154 *
155 * @details While L1-level driver features are exclusively implemented by
156 * drivers and MAY be mandatory to support certain application requirements, L2
157 * features SHOULD be optional by default and only need to be implemented for
158 * performance optimization or precise timing as deemed necessary by driver
159 * maintainers. Fallback implementations ("Soft MAC") SHOULD be provided in the
160 * driver-independent L2 layer for all L2/MAC features especially if these
161 * features are not implemented in vendor hardware/firmware by a majority of
162 * existing in-tree drivers. If, however, a driver offers offloading
163 * opportunities then L2 implementations SHALL delegate performance critical or
164 * resource intensive tasks to the driver.
165 *
166 * All drivers SHALL support two externally observable interface operational
167 * states: "UP" and "DOWN". Drivers MAY additionally support a "TESTING"
168 * interface state (see `continuous_carrier()`).
169 *
170 * The following rules apply:
171 * * An interface is considered "UP" when it is able to transmit and receive
172 * packets, "DOWN" otherwise (see precise definitions of the corresponding
173 * ifOperStatus values in RFC 2863, section 3.1.14.
174 * * Upper layers will assume that the interface managed by the driver is "UP"
175 * after a call to `start()` returned zero or `-EALREADY`. Upper layers assume
176 * that the interface is "DOWN" after calling `stop()` returned zero or
177 * `-EALREADY`.
178 * * The driver SHALL block `start()`/`stop()` calls until the interface fully
179 * transitioned to the new state (e.g. the receiver is operational, ongoing
180 * transmissions were finished, etc.). Drivers SHOULD yield the calling thread
181 * (i.e. "sleep") if waiting for the new state without CPU interaction is
182 * possible.
183 * * Drivers are responsible of guaranteeing atomicity of state changes.
184 * Appropriate means of synchronization SHALL be implemented (locking, atomic
185 * flags, ...).
186 * * The driver SHALL NOT change the interface's "UP"/"DOWN" state on its own.
187 * Initially, the interface SHALL be in the "DOWN" state.
188 * * If calls to `start()`/`stop()` return any other value than zero or
189 * `-EALREADY`, upper layers will consider the interface to be in a
190 * "lowerLayerDown" state as defined in RFC 2863.
191 * * The RFC 2863 "dormant", "unknown" and "notPresent" ifOperStatus states are
192 * currently not supported.
193 *
194 */
195struct dectnrp_driver_api {
196
197 /**
198 * @brief network interface API
199 *
200 * @note Network devices must extend the network interface API. It is
201 * therefore mandatory to place it at the top of the driver API struct so
202 * that it can be cast to a network interface.
203 */
204 struct net_if_api iface_api;
205
206 /**
207 * @brief Start the device.
208 *
209 * @param dev pointer to DECTNRP driver device
210 *
211 * @retval 0 The driver was successfully started.
212 * @retval -EIO The driver could not be started.
213 */
214 int (*start)(const struct device *dev);
215
216 /**
217 * @brief Stop the device.
218 *
219 * @param dev pointer to DECTNRP driver device
220 *
221 * @retval 0 The driver was successfully stopped.
222 * @retval -EIO The driver could not be stopped.
223 */
224 int (*stop)(const struct device *dev);
225
226 /**
227 * @brief Get the device driver capabilities.
228 *
229 * @param dev pointer to DECTNRP driver device
230 * @param[out] cap pointer to capabilities provided by @p dev
231 *
232 * @retval 0 Capabilities successfully written to @p cap.
233 * @retval -EIO The driver has some error.
234 */
235 int (*get_capabilities)(const struct device *dev, struct device_capabilities* cap);
236
237 /**
238 * @brief Set or update driver configuration.
239 *
240 * @details The method blocks until the interface has been reconfigured
241 * atomically with respect to ongoing package reception, transmission or
242 * any other ongoing driver operation.
243 *
244 * @param dev pointer to DECTNRP driver device
245 * @param type the configuration type to be set
246 * @param config the configuration parameters to be set for the given
247 * configuration type
248 *
249 * @retval 0 configuration successful
250 * @retval -EINVAL The configuration parameters are invalid for the
251 * given configuration type.
252 * @retval -ENOTSUP The given configuration type is not supported by
253 * this driver.
254 * @retval -EACCES The given configuration type is supported by this
255 * driver but cannot be configured in the current interface operational
256 * state.
257 * @retval -ENOMEM The configuration cannot be saved due to missing
258 * memory resources.
259 * @retval -ENOENT The resource referenced in the configuration
260 * parameters cannot be found in the configuration.
261 * @retval -EIO An internal error occurred while trying to configure the
262 * given configuration parameter.
263 */
264 int (*configure)(const struct device *dev, enum dectnrp_config_type type,
265 const struct dectnrp_config *config);
266
267 /**
268 * @brief Get the current modem time.
269 *
270 * @param dev pointer to DECTNRP driver device
271 *
272 * @return nanoseconds relative to the network subsystem's local clock,
273 * -1 if an error occurred or the operation is not supported
274 */
275 net_time_t (*get_time)(const struct device *dev);
276
277#ifdef CONFIG_DECTNRP_DRIVER_SCHEDULED_API
278
279 /**
280 * @brief Schedule given operation @p op.
281 *
282 * @note This function is non-blocking and just provides @p op to the driver which
283 * in turn notifies completion back via dectnrp_event_cb_t.
284 *
285 * @param dev pointer to DECTNRP driver device
286 * @param op the operation to be scheduled.
287 *
288 * @retval 0 Operation @p op successfully scheduled.
289 * @retval -EIO The driver has some error.
290 */
291 int (*schedule)(const struct device *dev, struct dectnrp_driver_op *op);
292
293#endif /* CONFIG_DECTNRP_DRIVER_SCHEDULED_API */
294
295#ifdef CONFIG_DECTNRP_DRIVER_BLOCKING_API
296
297 /**
298 * @brief Set current channel.
299 *
300 * @param dev pointer to DECTNRP driver device
301 * @param channel the number of the channel to be set.
302 *
303 * @retval 0 channel was successfully set
304 * @retval -EIO The channel could not be set.
305 */
306 int (*set_channel)(const struct device *dev, uint16_t channel);
307
308 /**
309 * @brief Receive a packet fragment as a single message.
310 *
311 * @note The radio channel must be set prior to calling this function.
312 *
313 * @param dev pointer to DECTNRP driver device
314 * @param mode the reception mode flags.
315 * @param start
316 * @param duration
317 * @param[in,out] pkt
318 *
319 */
320 int (*rx)(const struct device *dev, struct dectnrp_rx_mode mode, net_time_t start,
321 uint32_t duration, struct net_pkt *pkt);
322
323 /**
324 * @brief Transmit a packet fragment as a single message
325 *
326 * @note The radio channel must be set prior to calling this function.
327 *
328 * @param dev pointer to DECTNRP driver device
329 * @param mode the transmission mode flags.
330 * @param pkt pointer to the network packet to be transmitted.
331 * @param frag pointer to a network buffer containing a single fragment
332 * with the frame data to be transmitted
333 *
334 * @retval 0 The frame was successfully sent or scheduled.
335 * @retval -EIO The frame could not be sent due to some unspecified
336 * driver error (e.g. the driver being busy).
337 */
338 int (*tx)(const struct device *dev, struct dectnrp_tx_mode mode, struct net_pkt *pkt,
339 struct net_buf *frag);
340
341 /**
342 * @brief Run a RSSI-1 scan on current channel
343 *
344 * @note The radio channel must be set prior to calling this function.
345 *
346 * @param dev pointer to DECTNRP driver device
347 * @param mode the rssi1 mode flags.
348 * @param subslots.
349 * @param[out] result
350 *
351 * @retval 0 The rssi1 operation frame was successfully scheduled.
352 */
353 int (*rssi1)(const struct device *dev, struct dectnrp_rssi_mode mode,
354 uint32_t subslots, struct dectnrp_rssi1_result *result);
355
356#endif /* CONFIG_DECTNRP_DRIVER_BLOCKING_API */
357
358};
359
360/* Make sure that the network interface API is properly setup inside
361 * DECTNRP driver API struct (it is the first one).
362 */
363BUILD_ASSERT(offsetof(struct dectnrp_driver_api, iface_api) == 0);
364
365/**
366 * @name DECTNRP driver callbacks
367 * @{
368 */
369
370/**
371 * @brief DECTNRP driver initialization callback into L2 called by drivers
372 * to initialize the active L2 stack for a given interface.
373 *
374 * @details Drivers must call this function as part of their own initialization
375 * routine.
376 *
377 * Note: This function is part of Zephyr's DECTNRP stack driver -> L2
378 * "inversion-of-control" adaptation API and must be implemented by all
379 * DECTNRP L2 stacks.
380 *
381 * @param iface A valid pointer on a network interface
382 */
383void dectnrp_init(struct net_if *iface);
384
385/** @} */
386
387/** @} */
388
389#ifdef __cplusplus
390}
391#endif
392
393#endif /* DECTNRP_DRIVER_H_ */