1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT zephyr_ieee802154_uart_pipe
8
9 #define LOG_MODULE_NAME ieee802154_uart_pipe
10 #define LOG_LEVEL CONFIG_IEEE802154_DRIVER_LOG_LEVEL
11
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
14
15 #include <errno.h>
16
17 #include <zephyr/kernel.h>
18 #include <zephyr/arch/cpu.h>
19
20 #include <zephyr/device.h>
21 #include <zephyr/init.h>
22 #include <zephyr/net/net_if.h>
23 #include <zephyr/net/net_pkt.h>
24 #include <zephyr/random/random.h>
25
26 #include <zephyr/drivers/uart_pipe.h>
27 #include <zephyr/net/ieee802154_radio.h>
28
29 #include "ieee802154_uart_pipe.h"
30
31 #define PAN_ID_OFFSET 3 /* Pan Id offset */
32 #define DEST_ADDR_OFFSET 5 /* Destination offset address*/
33 #define DEST_ADDR_TYPE_OFFSET 1 /* Destination address type */
34
35 #define DEST_ADDR_TYPE_MASK 0x0c /* Mask for destination address type */
36
37 #define DEST_ADDR_TYPE_SHORT 0x08 /* Short destination address type */
38 #define DEST_ADDR_TYPE_EXTENDED 0x0c /* Extended destination address type */
39
40 #define PAN_ID_SIZE 2 /* Size of Pan Id */
41 #define SHORT_ADDRESS_SIZE 2 /* Size of Short Mac Address */
42 #define EXTENDED_ADDRESS_SIZE 8 /* Size of Extended Mac Address */
43
44 /* Broadcast Short Address */
45 #define BROADCAST_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff})
46
47 static uint8_t dev_pan_id[PAN_ID_SIZE]; /* Device Pan Id */
48 static uint8_t dev_short_addr[SHORT_ADDRESS_SIZE]; /* Device Short Address */
49 static uint8_t dev_ext_addr[EXTENDED_ADDRESS_SIZE]; /* Device Extended Address */
50
51 /** Singleton device used in uart pipe callback */
52 static const struct device *upipe_dev;
53
54 #if defined(CONFIG_IEEE802154_UPIPE_HW_FILTER)
55
received_dest_addr_matched(uint8_t * rx_buffer)56 static bool received_dest_addr_matched(uint8_t *rx_buffer)
57 {
58 struct upipe_context *upipe = upipe_dev->data;
59
60 /* Check destination PAN Id */
61 if (memcmp(&rx_buffer[PAN_ID_OFFSET],
62 dev_pan_id, PAN_ID_SIZE) != 0 &&
63 memcmp(&rx_buffer[PAN_ID_OFFSET],
64 BROADCAST_ADDRESS, PAN_ID_SIZE) != 0) {
65 return false;
66 }
67
68 /* Check destination address */
69 switch (rx_buffer[DEST_ADDR_TYPE_OFFSET] & DEST_ADDR_TYPE_MASK) {
70 case DEST_ADDR_TYPE_SHORT:
71 /* First check if the destination is broadcast */
72 /* If not broadcast, check if length and address matches */
73 if (memcmp(&rx_buffer[DEST_ADDR_OFFSET],
74 BROADCAST_ADDRESS,
75 SHORT_ADDRESS_SIZE) != 0 &&
76 (net_if_get_link_addr(upipe->iface)->len !=
77 SHORT_ADDRESS_SIZE ||
78 memcmp(&rx_buffer[DEST_ADDR_OFFSET],
79 dev_short_addr,
80 SHORT_ADDRESS_SIZE) != 0)) {
81 return false;
82 }
83 break;
84
85 case DEST_ADDR_TYPE_EXTENDED:
86 /* If not broadcast, check if length and address matches */
87 if (net_if_get_link_addr(upipe->iface)->len !=
88 EXTENDED_ADDRESS_SIZE ||
89 memcmp(&rx_buffer[DEST_ADDR_OFFSET],
90 dev_ext_addr, EXTENDED_ADDRESS_SIZE) != 0) {
91 return false;
92 }
93 break;
94
95 default:
96 return false;
97 }
98
99 return true;
100 }
101
102 #endif
103
upipe_rx(uint8_t * buf,size_t * off)104 static uint8_t *upipe_rx(uint8_t *buf, size_t *off)
105 {
106 struct net_pkt *pkt = NULL;
107 struct upipe_context *upipe;
108
109 if (!upipe_dev) {
110 goto done;
111 }
112
113 upipe = upipe_dev->data;
114 if (!upipe->rx && *buf == UART_PIPE_RADIO_15_4_FRAME_TYPE) {
115 upipe->rx = true;
116 goto done;
117 }
118
119 if (!upipe->rx_len) {
120 if (*buf > 127) {
121 goto flush;
122 }
123
124 upipe->rx_len = *buf;
125 goto done;
126 }
127
128 upipe->rx_buf[upipe->rx_off++] = *buf;
129
130 if (upipe->rx_len == upipe->rx_off) {
131 struct net_buf *frag;
132
133 pkt = net_pkt_rx_alloc(K_NO_WAIT);
134 if (!pkt) {
135 LOG_DBG("No pkt available");
136 goto flush;
137 }
138
139 frag = net_pkt_get_frag(pkt, upipe->rx_len, K_NO_WAIT);
140 if (!frag) {
141 LOG_DBG("No fragment available");
142 goto out;
143 }
144
145 net_pkt_frag_insert(pkt, frag);
146
147 memcpy(frag->data, upipe->rx_buf, upipe->rx_len);
148 net_buf_add(frag, upipe->rx_len);
149
150 #if defined(CONFIG_IEEE802154_UPIPE_HW_FILTER)
151 if (received_dest_addr_matched(frag->data) == false) {
152 LOG_DBG("Packet received is not addressed to me");
153 goto out;
154 }
155 #endif
156
157 if (ieee802154_handle_ack(upipe->iface, pkt) == NET_OK) {
158 LOG_DBG("ACK packet handled");
159 goto out;
160 }
161
162 LOG_DBG("Caught a packet (%u)", upipe->rx_len);
163 if (net_recv_data(upipe->iface, pkt) < 0) {
164 LOG_DBG("Packet dropped by NET stack");
165 goto out;
166 }
167
168 goto flush;
169 out:
170 net_pkt_unref(pkt);
171 flush:
172 upipe->rx = false;
173 upipe->rx_len = 0U;
174 upipe->rx_off = 0U;
175 }
176 done:
177 *off = 0;
178
179 return buf;
180 }
181
upipe_get_capabilities(const struct device * dev)182 static enum ieee802154_hw_caps upipe_get_capabilities(const struct device *dev)
183 {
184 return IEEE802154_HW_FCS | IEEE802154_HW_FILTER;
185 }
186
upipe_cca(const struct device * dev)187 static int upipe_cca(const struct device *dev)
188 {
189 struct upipe_context *upipe = dev->data;
190
191 if (upipe->stopped) {
192 return -EIO;
193 }
194
195 return 0;
196 }
197
upipe_set_channel(const struct device * dev,uint16_t channel)198 static int upipe_set_channel(const struct device *dev, uint16_t channel)
199 {
200 ARG_UNUSED(dev);
201 ARG_UNUSED(channel);
202
203 return 0;
204 }
205
upipe_set_pan_id(const struct device * dev,uint16_t pan_id)206 static int upipe_set_pan_id(const struct device *dev, uint16_t pan_id)
207 {
208 uint8_t pan_id_le[2];
209
210 ARG_UNUSED(dev);
211
212 sys_put_le16(pan_id, pan_id_le);
213 memcpy(dev_pan_id, pan_id_le, PAN_ID_SIZE);
214
215 return 0;
216 }
217
upipe_set_short_addr(const struct device * dev,uint16_t short_addr)218 static int upipe_set_short_addr(const struct device *dev, uint16_t short_addr)
219 {
220 uint8_t short_addr_le[2];
221
222 ARG_UNUSED(dev);
223
224 sys_put_le16(short_addr, short_addr_le);
225 memcpy(dev_short_addr, short_addr_le, SHORT_ADDRESS_SIZE);
226
227 return 0;
228 }
229
upipe_set_ieee_addr(const struct device * dev,const uint8_t * ieee_addr)230 static int upipe_set_ieee_addr(const struct device *dev,
231 const uint8_t *ieee_addr)
232 {
233 ARG_UNUSED(dev);
234
235 memcpy(dev_ext_addr, ieee_addr, EXTENDED_ADDRESS_SIZE);
236
237 return 0;
238 }
239
upipe_filter(const struct device * dev,bool set,enum ieee802154_filter_type type,const struct ieee802154_filter * filter)240 static int upipe_filter(const struct device *dev,
241 bool set,
242 enum ieee802154_filter_type type,
243 const struct ieee802154_filter *filter)
244 {
245 LOG_DBG("Applying filter %u", type);
246
247 if (!set) {
248 return -ENOTSUP;
249 }
250
251 if (type == IEEE802154_FILTER_TYPE_IEEE_ADDR) {
252 return upipe_set_ieee_addr(dev, filter->ieee_addr);
253 } else if (type == IEEE802154_FILTER_TYPE_SHORT_ADDR) {
254 return upipe_set_short_addr(dev, filter->short_addr);
255 } else if (type == IEEE802154_FILTER_TYPE_PAN_ID) {
256 return upipe_set_pan_id(dev, filter->pan_id);
257 }
258
259 return -ENOTSUP;
260 }
261
upipe_set_txpower(const struct device * dev,int16_t dbm)262 static int upipe_set_txpower(const struct device *dev, int16_t dbm)
263 {
264 ARG_UNUSED(dev);
265 ARG_UNUSED(dbm);
266
267 return 0;
268 }
269
upipe_tx(const struct device * dev,enum ieee802154_tx_mode mode,struct net_pkt * pkt,struct net_buf * frag)270 static int upipe_tx(const struct device *dev,
271 enum ieee802154_tx_mode mode,
272 struct net_pkt *pkt,
273 struct net_buf *frag)
274 {
275 struct upipe_context *upipe = dev->data;
276 uint8_t *pkt_buf = frag->data;
277 uint8_t len = frag->len;
278 uint8_t i, data;
279
280 if (mode != IEEE802154_TX_MODE_DIRECT) {
281 NET_ERR("TX mode %d not supported", mode);
282 return -ENOTSUP;
283 }
284
285 LOG_DBG("%p (%u)", frag, len);
286
287 if (upipe->stopped) {
288 return -EIO;
289 }
290
291 data = UART_PIPE_RADIO_15_4_FRAME_TYPE;
292 uart_pipe_send(&data, 1);
293
294 data = len;
295 uart_pipe_send(&data, 1);
296
297 for (i = 0U; i < len; i++) {
298 uart_pipe_send(pkt_buf+i, 1);
299 }
300
301 return 0;
302 }
303
upipe_start(const struct device * dev)304 static int upipe_start(const struct device *dev)
305 {
306 struct upipe_context *upipe = dev->data;
307
308 if (!upipe->stopped) {
309 return -EALREADY;
310 }
311
312 upipe->stopped = false;
313
314 return 0;
315 }
316
upipe_stop(const struct device * dev)317 static int upipe_stop(const struct device *dev)
318 {
319 struct upipe_context *upipe = dev->data;
320
321 if (upipe->stopped) {
322 return -EALREADY;
323 }
324
325 upipe->stopped = true;
326
327 return 0;
328 }
329
330 /* driver-allocated attribute memory - constant across all driver instances */
331 IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
332
333 /* API implementation: attr_get */
upipe_attr_get(const struct device * dev,enum ieee802154_attr attr,struct ieee802154_attr_value * value)334 static int upipe_attr_get(const struct device *dev, enum ieee802154_attr attr,
335 struct ieee802154_attr_value *value)
336 {
337 ARG_UNUSED(dev);
338
339 return ieee802154_attr_get_channel_page_and_range(
340 attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
341 &drv_attr.phy_supported_channels, value);
342 }
343
upipe_init(const struct device * dev)344 static int upipe_init(const struct device *dev)
345 {
346 struct upipe_context *upipe = dev->data;
347
348 (void)memset(upipe, 0, sizeof(struct upipe_context));
349
350 uart_pipe_register(upipe->uart_pipe_buf, 1, upipe_rx);
351
352 upipe_stop(dev);
353
354 return 0;
355 }
356
get_mac(const struct device * dev)357 static inline uint8_t *get_mac(const struct device *dev)
358 {
359 struct upipe_context *upipe = dev->data;
360
361 upipe->mac_addr[0] = 0x00;
362 upipe->mac_addr[1] = 0x10;
363 upipe->mac_addr[2] = 0x20;
364 upipe->mac_addr[3] = 0x30;
365
366 #if defined(CONFIG_IEEE802154_UPIPE_RANDOM_MAC)
367 UNALIGNED_PUT(sys_cpu_to_be32(sys_rand32_get()),
368 (uint32_t *) ((uint8_t *)upipe->mac_addr+4));
369 #else
370 upipe->mac_addr[4] = CONFIG_IEEE802154_UPIPE_MAC4;
371 upipe->mac_addr[5] = CONFIG_IEEE802154_UPIPE_MAC5;
372 upipe->mac_addr[6] = CONFIG_IEEE802154_UPIPE_MAC6;
373 upipe->mac_addr[7] = CONFIG_IEEE802154_UPIPE_MAC7;
374 #endif
375
376 return upipe->mac_addr;
377 }
378
upipe_iface_init(struct net_if * iface)379 static void upipe_iface_init(struct net_if *iface)
380 {
381 const struct device *dev = net_if_get_device(iface);
382 struct upipe_context *upipe = dev->data;
383 uint8_t *mac = get_mac(dev);
384
385 net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154);
386
387 upipe_dev = dev;
388 upipe->iface = iface;
389
390 ieee802154_init(iface);
391 }
392
393 static struct upipe_context upipe_context_data;
394
395 static struct ieee802154_radio_api upipe_radio_api = {
396 .iface_api.init = upipe_iface_init,
397
398 .get_capabilities = upipe_get_capabilities,
399 .cca = upipe_cca,
400 .set_channel = upipe_set_channel,
401 .filter = upipe_filter,
402 .set_txpower = upipe_set_txpower,
403 .tx = upipe_tx,
404 .start = upipe_start,
405 .stop = upipe_stop,
406 .attr_get = upipe_attr_get,
407 };
408
409 NET_DEVICE_DT_INST_DEFINE(0, upipe_init, NULL, &upipe_context_data, NULL,
410 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &upipe_radio_api,
411 IEEE802154_L2, NET_L2_GET_CTX_TYPE(IEEE802154_L2),
412 125);
413