1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public IEEE 802.15.4 Radio API
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_
13 #define ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_
14 
15 #include <zephyr/device.h>
16 #include <zephyr/net/net_if.h>
17 #include <zephyr/net/net_pkt.h>
18 #include <zephyr/net/ieee802154.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /**
25  * @addtogroup ieee802154
26  * @{
27  */
28 
29 /**
30  * @brief IEEE 802.15.4 Channel assignments
31  *
32  * Channel numbering for 868 MHz, 915 MHz, and 2450 MHz bands (channel page zero).
33  *
34  * - Channel 0 is for 868.3 MHz.
35  * - Channels 1-10 are for 906 to 924 MHz with 2 MHz channel spacing.
36  * - Channels 11-26 are for 2405 to 2530 MHz with 5 MHz channel spacing.
37  *
38  * For more information, please refer to 802.15.4-2015 Section 10.1.2.2.
39  */
40 enum ieee802154_channel {
41 	IEEE802154_SUB_GHZ_CHANNEL_MIN = 0,
42 	IEEE802154_SUB_GHZ_CHANNEL_MAX = 10,
43 	IEEE802154_2_4_GHZ_CHANNEL_MIN = 11,
44 	IEEE802154_2_4_GHZ_CHANNEL_MAX = 26,
45 };
46 
47 enum ieee802154_hw_caps {
48 	IEEE802154_HW_FCS	  = BIT(0), /* Frame Check-Sum supported */
49 	IEEE802154_HW_PROMISC	  = BIT(1), /* Promiscuous mode supported */
50 	IEEE802154_HW_FILTER	  = BIT(2), /* Filter PAN ID, long/short addr */
51 	IEEE802154_HW_CSMA	  = BIT(3), /* CSMA-CA supported */
52 	IEEE802154_HW_2_4_GHZ	  = BIT(4), /* 2.4Ghz radio supported */
53 	IEEE802154_HW_TX_RX_ACK	  = BIT(5), /* Handles ACK request on TX */
54 	IEEE802154_HW_SUB_GHZ	  = BIT(6), /* Sub-GHz radio supported */
55 	IEEE802154_HW_ENERGY_SCAN = BIT(7), /* Energy scan supported */
56 	IEEE802154_HW_TXTIME	  = BIT(8), /* TX at specified time supported */
57 	IEEE802154_HW_SLEEP_TO_TX = BIT(9), /* TX directly from sleep supported */
58 	IEEE802154_HW_TX_SEC	  = BIT(10), /* TX security handling supported */
59 	IEEE802154_HW_RXTIME	  = BIT(11), /* RX at specified time supported */
60 };
61 
62 enum ieee802154_filter_type {
63 	IEEE802154_FILTER_TYPE_IEEE_ADDR,
64 	IEEE802154_FILTER_TYPE_SHORT_ADDR,
65 	IEEE802154_FILTER_TYPE_PAN_ID,
66 	IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR,
67 	IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR,
68 };
69 
70 enum ieee802154_event {
71 	IEEE802154_EVENT_TX_STARTED, /* Data transmission started */
72 	IEEE802154_EVENT_RX_FAILED, /* Data reception failed */
73 	IEEE802154_EVENT_SLEEP, /* Sleep pending */
74 };
75 
76 enum ieee802154_rx_fail_reason {
77 	IEEE802154_RX_FAIL_NOT_RECEIVED,  /* Nothing received */
78 	IEEE802154_RX_FAIL_INVALID_FCS,   /* Frame had invalid checksum */
79 	IEEE802154_RX_FAIL_ADDR_FILTERED, /* Address did not match */
80 	IEEE802154_RX_FAIL_OTHER	  /* General reason */
81 };
82 
83 typedef void (*energy_scan_done_cb_t)(const struct device *dev,
84 				      int16_t max_ed);
85 
86 typedef void (*ieee802154_event_cb_t)(const struct device *dev,
87 				      enum ieee802154_event evt,
88 				      void *event_params);
89 
90 struct ieee802154_filter {
91 /** @cond ignore */
92 	union {
93 		uint8_t *ieee_addr; /* in little endian */
94 		uint16_t short_addr; /* in CPU byte order */
95 		uint16_t pan_id; /* in CPU byte order */
96 	};
97 /* @endcond */
98 };
99 
100 struct ieee802154_key {
101 	uint8_t *key_value;
102 	uint32_t key_frame_counter;
103 	bool frame_counter_per_key;
104 	uint8_t key_id_mode;
105 	uint8_t key_index;
106 };
107 
108 /** IEEE802.15.4 Transmission mode. */
109 enum ieee802154_tx_mode {
110 	/** Transmit packet immediately, no CCA. */
111 	IEEE802154_TX_MODE_DIRECT,
112 
113 	/** Perform CCA before packet transmission. */
114 	IEEE802154_TX_MODE_CCA,
115 
116 	/** Perform full CSMA CA procedure before packet transmission. */
117 	IEEE802154_TX_MODE_CSMA_CA,
118 
119 	/** Transmit packet in the future, at specified time, no CCA. */
120 	IEEE802154_TX_MODE_TXTIME,
121 
122 	/** Transmit packet in the future, perform CCA before transmission. */
123 	IEEE802154_TX_MODE_TXTIME_CCA,
124 };
125 
126 /** IEEE802.15.4 Frame Pending Bit table address matching mode. */
127 enum ieee802154_fpb_mode {
128 	/** The pending bit shall be set only for addresses found in the list.
129 	 */
130 	IEEE802154_FPB_ADDR_MATCH_THREAD,
131 
132 	/** The pending bit shall be cleared for short addresses found in
133 	 *  the list.
134 	 */
135 	IEEE802154_FPB_ADDR_MATCH_ZIGBEE,
136 };
137 
138 /** IEEE802.15.4 driver configuration types. */
139 enum ieee802154_config_type {
140 	/** Indicates how radio driver should set Frame Pending bit in ACK
141 	 *  responses for Data Requests. If enabled, radio driver should
142 	 *  determine whether to set the bit or not based on the information
143 	 *  provided with ``IEEE802154_CONFIG_ACK_FPB`` config and FPB address
144 	 *  matching mode specified. Otherwise, Frame Pending bit should be set
145 	 *  to ``1`` (see IEEE Std 802.15.4-2006, 7.2.2.3.1).
146 	 */
147 	IEEE802154_CONFIG_AUTO_ACK_FPB,
148 
149 	/** Indicates whether to set ACK Frame Pending bit for specific address
150 	 *  or not. Disabling the Frame Pending bit with no address provided
151 	 *  (NULL pointer) should disable it for all enabled addresses.
152 	 */
153 	IEEE802154_CONFIG_ACK_FPB,
154 
155 	/** Indicates whether the device is a PAN coordinator. */
156 	IEEE802154_CONFIG_PAN_COORDINATOR,
157 
158 	/** Enable/disable promiscuous mode. */
159 	IEEE802154_CONFIG_PROMISCUOUS,
160 
161 	/** Specifies new radio event handler. Specifying NULL as a handler
162 	 *  will disable radio events notification.
163 	 */
164 	IEEE802154_CONFIG_EVENT_HANDLER,
165 
166 	/** Updates MAC keys and key index for radios supporting transmit security. */
167 	IEEE802154_CONFIG_MAC_KEYS,
168 
169 	/** Sets the current MAC frame counter value for radios supporting transmit security. */
170 	IEEE802154_CONFIG_FRAME_COUNTER,
171 
172 	/** Sets the current MAC frame counter value if the provided value is greater than
173 	 * the current one.
174 	 */
175 
176 	IEEE802154_CONFIG_FRAME_COUNTER_IF_LARGER,
177 
178 	/** Configure a radio reception slot. This can be used for any scheduler reception, e.g.:
179 	 *  Zigbee GP device, CSL, TSCH, etc.
180 	 */
181 	IEEE802154_CONFIG_RX_SLOT,
182 
183 	/** Configure CSL receiver (Endpoint) period
184 	 *
185 	 *  In order to configure a CSL receiver the upper layer should combine several
186 	 *  configuration options in the following way:
187 	 *    1. Use ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` once to inform the radio driver of the
188 	 *  short and extended addresses of the peer to which it should inject CSL IEs.
189 	 *    2. Use ``IEEE802154_CONFIG_CSL_RX_TIME`` periodically, before each use of
190 	 *  ``IEEE802154_CONFIG_CSL_PERIOD`` setting parameters of the nearest CSL RX window, and
191 	 *  before each use of IEEE_CONFIG_RX_SLOT setting parameters of the following (not the
192 	 *  nearest one) CSL RX window, to allow the radio driver to calculate the proper CSL Phase
193 	 *  to the nearest CSL window to inject in the CSL IEs for both transmitted data and ack
194 	 *  frames.
195 	 *    3. Use ``IEEE802154_CONFIG_CSL_PERIOD`` on each value change to update the current CSL
196 	 *  period value which will be injected in the CSL IEs together with the CSL Phase based on
197 	 *  ``IEEE802154_CONFIG_CSL_RX_TIME``.
198 	 *    4. Use ``IEEE802154_CONFIG_RX_SLOT`` periodically to schedule the immediate receive
199 	 *  window earlier enough before the expected window start time, taking into account
200 	 *  possible clock drifts and scheduling uncertainties.
201 	 *
202 	 *  This diagram shows the usage of the four options over time:
203 	 *        Start CSL                                  Schedule CSL window
204 	 *
205 	 *    ENH_ACK_HEADER_IE                        CSL_RX_TIME (following window)
206 	 *         |                                        |
207 	 *         | CSL_RX_TIME (nearest window)           | RX_SLOT (nearest window)
208 	 *         |    |                                   |   |
209 	 *         |    | CSL_PERIOD                        |   |
210 	 *         |    |    |                              |   |
211 	 *         v    v    v                              v   v
212 	 *    ----------------------------------------------------------[ CSL window ]-----+
213 	 *                                            ^                                    |
214 	 *                                            |                                    |
215 	 *                                            +--------------------- loop ---------+
216 	 */
217 	IEEE802154_CONFIG_CSL_PERIOD,
218 
219 	/** Configure the next CSL receive window center, in units of microseconds,
220 	 *  based on the radio time.
221 	 */
222 	IEEE802154_CONFIG_CSL_RX_TIME,
223 
224 	/** Indicates whether to inject IE into ENH ACK Frame for specific address
225 	 *  or not. Disabling the ENH ACK with no address provided (NULL pointer)
226 	 *  should disable it for all enabled addresses.
227 	 */
228 	IEEE802154_CONFIG_ENH_ACK_HEADER_IE,
229 };
230 
231 /** IEEE802.15.4 driver configuration data. */
232 struct ieee802154_config {
233 	/** Configuration data. */
234 	union {
235 		/** ``IEEE802154_CONFIG_AUTO_ACK_FPB`` */
236 		struct {
237 			bool enabled;
238 			enum ieee802154_fpb_mode mode;
239 		} auto_ack_fpb;
240 
241 		/** ``IEEE802154_CONFIG_ACK_FPB`` */
242 		struct {
243 			uint8_t *addr; /* in little endian for both, short and extended address */
244 			bool extended;
245 			bool enabled;
246 		} ack_fpb;
247 
248 		/** ``IEEE802154_CONFIG_PAN_COORDINATOR`` */
249 		bool pan_coordinator;
250 
251 		/** ``IEEE802154_CONFIG_PROMISCUOUS`` */
252 		bool promiscuous;
253 
254 		/** ``IEEE802154_CONFIG_EVENT_HANDLER`` */
255 		ieee802154_event_cb_t event_handler;
256 
257 		/** ``IEEE802154_CONFIG_MAC_KEYS``
258 		 *  Pointer to an array containing a list of keys used
259 		 *  for MAC encryption. Refer to secKeyIdLookupDescriptor and
260 		 *  secKeyDescriptor in IEEE 802.15.4
261 		 *
262 		 *  key_value field points to a buffer containing the 16 byte
263 		 *  key. The buffer is copied by the callee.
264 		 *
265 		 *  The variable length array is terminated by key_value field
266 		 *  set to NULL.
267 		 */
268 		struct ieee802154_key *mac_keys;
269 
270 		/** ``IEEE802154_CONFIG_FRAME_COUNTER`` */
271 		uint32_t frame_counter;
272 
273 		/** ``IEEE802154_CONFIG_RX_SLOT`` */
274 		struct {
275 			uint8_t channel;
276 			uint32_t start;
277 			uint32_t duration;
278 		} rx_slot;
279 
280 		/** ``IEEE802154_CONFIG_CSL_PERIOD`` */
281 		uint32_t csl_period; /* in CPU byte order */
282 
283 		/** ``IEEE802154_CONFIG_CSL_RX_TIME`` */
284 		uint32_t csl_rx_time; /* in microseconds,
285 				       * based on ieee802154_radio_api.get_time()
286 				       */
287 
288 		/** ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` */
289 		struct {
290 			const uint8_t *data; /* header IEs to be added to the Enh-Ack frame in
291 					      * little endian byte order
292 					      */
293 			uint16_t data_len;
294 			uint16_t short_addr; /* in CPU byte order */
295 			/**
296 			 * The extended address is expected to be passed starting
297 			 * with the most significant octet and ending with the
298 			 * least significant octet.
299 			 * A device with an extended address 01:23:45:67:89:ab:cd:ef
300 			 * as written in the usual big-endian hex notation should
301 			 * provide a pointer to an array containing values in the
302 			 * exact same order.
303 			 */
304 			const uint8_t *ext_addr; /* in big endian */
305 		} ack_ie;
306 	};
307 };
308 
309 /**
310  * @brief IEEE 802.15.4 radio interface API.
311  *
312  */
313 struct ieee802154_radio_api {
314 	/**
315 	 * Mandatory to get in first position.
316 	 * A network device should indeed provide a pointer on such
317 	 * net_if_api structure. So we make current structure pointer
318 	 * that can be casted to a net_if_api structure pointer.
319 	 */
320 	struct net_if_api iface_api;
321 
322 	/** Get the device capabilities */
323 	enum ieee802154_hw_caps (*get_capabilities)(const struct device *dev);
324 
325 	/** Clear Channel Assessment - Check channel's activity */
326 	int (*cca)(const struct device *dev);
327 
328 	/** Set current channel, channel is in CPU byte order. */
329 	int (*set_channel)(const struct device *dev, uint16_t channel);
330 
331 	/** Set/Unset filters (for IEEE802154_HW_FILTER ) */
332 	int (*filter)(const struct device *dev,
333 		      bool set,
334 		      enum ieee802154_filter_type type,
335 		      const struct ieee802154_filter *filter);
336 
337 	/** Set TX power level in dbm */
338 	int (*set_txpower)(const struct device *dev, int16_t dbm);
339 
340 	/** Transmit a packet fragment */
341 	int (*tx)(const struct device *dev, enum ieee802154_tx_mode mode,
342 		  struct net_pkt *pkt, struct net_buf *frag);
343 
344 	/** Start the device */
345 	int (*start)(const struct device *dev);
346 
347 	/** Stop the device */
348 	int (*stop)(const struct device *dev);
349 
350 	/** Start continuous carrier wave transmission.
351 	 *  To leave this mode, `start()` or `stop()` API function should be called,
352 	 *  resulting in changing radio's state to receive or sleep, respectively.
353 	 */
354 	int (*continuous_carrier)(const struct device *dev);
355 
356 	/** Set specific radio driver configuration. */
357 	int (*configure)(const struct device *dev,
358 			 enum ieee802154_config_type type,
359 			 const struct ieee802154_config *config);
360 
361 	/** Get the available amount of Sub-GHz channels */
362 	uint16_t (*get_subg_channel_count)(const struct device *dev);
363 
364 	/** Run an energy detection scan.
365 	 *  Note: channel must be set prior to request this function.
366 	 *  duration parameter is in ms.
367 	 */
368 	int (*ed_scan)(const struct device *dev,
369 		       uint16_t duration,
370 		       energy_scan_done_cb_t done_cb);
371 
372 	/** Get the current radio time in microseconds */
373 	uint64_t (*get_time)(const struct device *dev);
374 
375 	/** Get the current accuracy, in units of ± ppm, of the clock used for
376 	 *  scheduling delayed receive or transmit radio operations.
377 	 *  Note: Implementations may optimize this value based on operational
378 	 *  conditions (i.e.: temperature).
379 	 */
380 	uint8_t (*get_sch_acc)(const struct device *dev);
381 };
382 
383 /* Make sure that the network interface API is properly setup inside
384  * IEEE 802154 radio API struct (it is the first one).
385  */
386 BUILD_ASSERT(offsetof(struct ieee802154_radio_api, iface_api) == 0);
387 
388 #define IEEE802154_AR_FLAG_SET (0x20)
389 
390 /**
391  * @brief Check if AR flag is set on the frame inside given net_pkt
392  *
393  * @param frag A valid pointer on a net_buf structure, must not be NULL,
394  *        and its length should be at least made of 1 byte (ACK frames
395  *        are the smallest frames on 15.4 and made of 3 bytes, not
396  *        not counting the FCS part).
397  *
398  * @return True if AR flag is set, False otherwise
399  */
ieee802154_is_ar_flag_set(struct net_buf * frag)400 static inline bool ieee802154_is_ar_flag_set(struct net_buf *frag)
401 {
402 	return (*frag->data & IEEE802154_AR_FLAG_SET);
403 }
404 
405 /**
406  * @brief Radio driver ACK handling function that hw drivers should use
407  *
408  * @details ACK handling requires fast handling and thus such function
409  *          helps to hook directly the hw drivers to the radio driver.
410  *
411  * @param iface A valid pointer on a network interface that received the packet
412  * @param pkt A valid pointer on a packet to check
413  *
414  * @return NET_OK if it was handled, NET_CONTINUE otherwise
415  */
416 extern enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface,
417 						    struct net_pkt *pkt);
418 
419 /**
420  * @brief Initialize L2 stack for a given interface
421  *
422  * @param iface A valid pointer on a network interface
423  */
424 #ifndef CONFIG_IEEE802154_RAW_MODE
425 void ieee802154_init(struct net_if *iface);
426 #else
427 #define ieee802154_init(_iface_)
428 #endif /* CONFIG_IEEE802154_RAW_MODE */
429 
430 #ifdef __cplusplus
431 }
432 #endif
433 
434 /**
435  * @}
436  */
437 
438 #endif /* ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_ */
439