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 <device.h>
16 #include <net/net_if.h>
17 #include <net/net_pkt.h>
18 #include <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.
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 hadling 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;
94 uint16_t short_addr;
95 uint16_t pan_id;
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 /** Configure a radio reception slot. This can be used for any scheduler reception, e.g.:
173 * Zigbee GP device, CSL, TSCH, etc.
174 *
175 * In order to configure a CSL receiver the upper layer should combine several
176 * configuration options in the following way:
177 * 1. Use ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` once to inform the radio driver of the
178 * short and extended addresses of the peer to which it should inject CSL IEs.
179 * 2. Use ``IEEE802154_CONFIG_CSL_RX_TIME`` periodically, before each use of
180 * ``IEEE802154_CONFIG_CSL_PERIOD`` setting parameters of the nearest CSL RX window, and
181 * before each use of IEEE_CONFIG_RX_SLOT setting parameters of the following (not the
182 * nearest one) CSL RX window, to allow the radio driver to calculate the proper CSL Phase
183 * to the nearest CSL window to inject in the CSL IEs for both transmitted data and ack
184 * frames.
185 * 3. Use ``IEEE802154_CONFIG_CSL_PERIOD`` on each value change to update the current CSL
186 * period value which will be injected in the CSL IEs together with the CSL Phase based on
187 * ``IEEE802154_CONFIG_CSL_RX_TIME``.
188 * 4. Use ``IEEE802154_CONFIG_RX_SLOT`` periodically to schedule the immediate receive
189 * window earlier enough before the expected window start time, taking into account
190 * possible clock drifts and scheduling uncertainties.
191 *
192 * This diagram shows the usage of the four options over time:
193 * Start CSL Schedule CSL window
194 *
195 * ENH_ACK_HEADER_IE CSL_RX_TIME (following window)
196 * | |
197 * | CSL_RX_TIME (nearest window) | RX_SLOT (nearest window)
198 * | | | |
199 * | | CSL_PERIOD | |
200 * | | | | |
201 * v v v v v
202 * ----------------------------------------------------------[ CSL window ]-----+
203 * ^ |
204 * | |
205 * +--------------------- loop ---------+
206 */
207 IEEE802154_CONFIG_RX_SLOT,
208
209 /** Configure CSL receiver (Endpoint) period */
210 IEEE802154_CONFIG_CSL_PERIOD,
211
212 /** Configure the next CSL receive window center, in units of microseconds,
213 * based on the radio time.
214 */
215 IEEE802154_CONFIG_CSL_RX_TIME,
216
217 /** Indicates whether to inject IE into ENH ACK Frame for specific address
218 * or not. Disabling the ENH ACK with no address provided (NULL pointer)
219 * should disable it for all enabled addresses.
220 */
221 IEEE802154_CONFIG_ENH_ACK_HEADER_IE,
222 };
223
224 /** IEEE802.15.4 driver configuration data. */
225 struct ieee802154_config {
226 /** Configuration data. */
227 union {
228 /** ``IEEE802154_CONFIG_AUTO_ACK_FPB`` */
229 struct {
230 bool enabled;
231 enum ieee802154_fpb_mode mode;
232 } auto_ack_fpb;
233
234 /** ``IEEE802154_CONFIG_ACK_FPB`` */
235 struct {
236 uint8_t *addr;
237 bool extended;
238 bool enabled;
239 } ack_fpb;
240
241 /** ``IEEE802154_CONFIG_PAN_COORDINATOR`` */
242 bool pan_coordinator;
243
244 /** ``IEEE802154_CONFIG_PROMISCUOUS`` */
245 bool promiscuous;
246
247 /** ``IEEE802154_CONFIG_EVENT_HANDLER`` */
248 ieee802154_event_cb_t event_handler;
249
250 /** ``IEEE802154_CONFIG_MAC_KEYS``
251 * Pointer to an array containing a list of keys used
252 * for MAC encryption. Refer to secKeyIdLookupDescriptor and
253 * secKeyDescriptor in IEEE 802.15.4
254 *
255 * key_value field points to a buffer containing the 16 byte
256 * key. The buffer is copied by the callee.
257 *
258 * The variable length array is terminated by key_value field
259 * set to NULL.
260 */
261 struct ieee802154_key *mac_keys;
262
263 /** ``IEEE802154_CONFIG_FRAME_COUNTER`` */
264 uint32_t frame_counter;
265
266 /** ``IEEE802154_CONFIG_RX_SLOT`` */
267 struct {
268 uint8_t channel;
269 uint32_t start;
270 uint32_t duration;
271 } rx_slot;
272
273 /** ``IEEE802154_CONFIG_CSL_PERIOD`` */
274 uint32_t csl_period;
275
276 /** ``IEEE802154_CONFIG_CSL_RX_TIME`` */
277 uint32_t csl_rx_time;
278
279 /** ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` */
280 struct {
281 const uint8_t *data;
282 uint16_t data_len;
283 uint16_t short_addr;
284 /**
285 * The extended address is expected to be passed starting
286 * with the leftmost octet and ending with the rightmost octet.
287 * A device with an extended address 01:23:45:67:89:ab:cd:ef
288 * should provide a pointer to array containing values in the
289 * same exact order.
290 */
291 const uint8_t *ext_addr;
292 } ack_ie;
293 };
294 };
295
296 /**
297 * @brief IEEE 802.15.4 radio interface API.
298 *
299 */
300 struct ieee802154_radio_api {
301 /**
302 * Mandatory to get in first position.
303 * A network device should indeed provide a pointer on such
304 * net_if_api structure. So we make current structure pointer
305 * that can be casted to a net_if_api structure pointer.
306 */
307 struct net_if_api iface_api;
308
309 /** Get the device capabilities */
310 enum ieee802154_hw_caps (*get_capabilities)(const struct device *dev);
311
312 /** Clear Channel Assesment - Check channel's activity */
313 int (*cca)(const struct device *dev);
314
315 /** Set current channel */
316 int (*set_channel)(const struct device *dev, uint16_t channel);
317
318 /** Set/Unset filters (for IEEE802154_HW_FILTER ) */
319 int (*filter)(const struct device *dev,
320 bool set,
321 enum ieee802154_filter_type type,
322 const struct ieee802154_filter *filter);
323
324 /** Set TX power level in dbm */
325 int (*set_txpower)(const struct device *dev, int16_t dbm);
326
327 /** Transmit a packet fragment */
328 int (*tx)(const struct device *dev, enum ieee802154_tx_mode mode,
329 struct net_pkt *pkt, struct net_buf *frag);
330
331 /** Start the device */
332 int (*start)(const struct device *dev);
333
334 /** Stop the device */
335 int (*stop)(const struct device *dev);
336
337 /** Set specific radio driver configuration. */
338 int (*configure)(const struct device *dev,
339 enum ieee802154_config_type type,
340 const struct ieee802154_config *config);
341
342 /** Get the available amount of Sub-GHz channels */
343 uint16_t (*get_subg_channel_count)(const struct device *dev);
344
345 /** Run an energy detection scan.
346 * Note: channel must be set prior to request this function.
347 * duration parameter is in ms.
348 */
349 int (*ed_scan)(const struct device *dev,
350 uint16_t duration,
351 energy_scan_done_cb_t done_cb);
352
353 /** Get the current radio time in microseconds */
354 uint64_t (*get_time)(const struct device *dev);
355
356 /** Get the current accuracy, in units of ± ppm, of the clock used for
357 * scheduling delayed receive or transmit radio operations.
358 * Note: Implementations may optimize this value based on operational
359 * conditions (i.e.: temperature).
360 */
361 uint8_t (*get_sch_acc)(const struct device *dev);
362 };
363
364 /* Make sure that the network interface API is properly setup inside
365 * IEEE 802154 radio API struct (it is the first one).
366 */
367 BUILD_ASSERT(offsetof(struct ieee802154_radio_api, iface_api) == 0);
368
369 #define IEEE802154_AR_FLAG_SET (0x20)
370
371 /**
372 * @brief Check if AR flag is set on the frame inside given net_pkt
373 *
374 * @param frag A valid pointer on a net_buf structure, must not be NULL,
375 * and its length should be at least made of 1 byte (ACK frames
376 * are the smallest frames on 15.4 and made of 3 bytes, not
377 * not counting the FCS part).
378 *
379 * @return True if AR flag is set, False otherwise
380 */
ieee802154_is_ar_flag_set(struct net_buf * frag)381 static inline bool ieee802154_is_ar_flag_set(struct net_buf *frag)
382 {
383 return (*frag->data & IEEE802154_AR_FLAG_SET);
384 }
385
386 /**
387 * @brief Radio driver ACK handling function that hw drivers should use
388 *
389 * @details ACK handling requires fast handling and thus such function
390 * helps to hook directly the hw drivers to the radio driver.
391 *
392 * @param iface A valid pointer on a network interface that received the packet
393 * @param pkt A valid pointer on a packet to check
394 *
395 * @return NET_OK if it was handled, NET_CONTINUE otherwise
396 */
397 extern enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface,
398 struct net_pkt *pkt);
399
400 /**
401 * @brief Initialize L2 stack for a given interface
402 *
403 * @param iface A valid pointer on a network interface
404 */
405 #ifndef CONFIG_IEEE802154_RAW_MODE
406 void ieee802154_init(struct net_if *iface);
407 #else
408 #define ieee802154_init(_iface_)
409 #endif /* CONFIG_IEEE802154_RAW_MODE */
410
411 #ifdef __cplusplus
412 }
413 #endif
414
415 /**
416 * @}
417 */
418
419 #endif /* ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_ */
420