dectnrp_driver_api.h

  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_ */