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 > IEEE802154_MAX_PHY_PACKET_SIZE) {
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 pkt = net_pkt_rx_alloc_with_buffer(upipe->iface, upipe->rx_len,
132 AF_UNSPEC, 0, K_NO_WAIT);
133 if (!pkt) {
134 LOG_DBG("No pkt available");
135 goto flush;
136 }
137
138 if (net_pkt_write(pkt, upipe->rx_buf, upipe->rx_len)) {
139 LOG_DBG("No content read?");
140 goto out;
141 }
142
143 #if defined(CONFIG_IEEE802154_UPIPE_HW_FILTER)
144 if (received_dest_addr_matched(pkt->buffer->data) == false) {
145 LOG_DBG("Packet received is not addressed to me");
146 goto out;
147 }
148 #endif
149
150 if (ieee802154_handle_ack(upipe->iface, pkt) == NET_OK) {
151 LOG_DBG("ACK packet handled");
152 goto out;
153 }
154
155 LOG_DBG("Caught a packet (%u)", upipe->rx_len);
156 if (net_recv_data(upipe->iface, pkt) < 0) {
157 LOG_DBG("Packet dropped by NET stack");
158 goto out;
159 }
160
161 goto flush;
162 out:
163 net_pkt_unref(pkt);
164 flush:
165 upipe->rx = false;
166 upipe->rx_len = 0U;
167 upipe->rx_off = 0U;
168 }
169 done:
170 *off = 0;
171
172 return buf;
173 }
174
upipe_get_capabilities(const struct device * dev)175 static enum ieee802154_hw_caps upipe_get_capabilities(const struct device *dev)
176 {
177 return IEEE802154_HW_FCS | IEEE802154_HW_FILTER;
178 }
179
upipe_cca(const struct device * dev)180 static int upipe_cca(const struct device *dev)
181 {
182 struct upipe_context *upipe = dev->data;
183
184 if (upipe->stopped) {
185 return -EIO;
186 }
187
188 return 0;
189 }
190
upipe_set_channel(const struct device * dev,uint16_t channel)191 static int upipe_set_channel(const struct device *dev, uint16_t channel)
192 {
193 ARG_UNUSED(dev);
194 ARG_UNUSED(channel);
195
196 return 0;
197 }
198
upipe_set_pan_id(const struct device * dev,uint16_t pan_id)199 static int upipe_set_pan_id(const struct device *dev, uint16_t pan_id)
200 {
201 uint8_t pan_id_le[2];
202
203 ARG_UNUSED(dev);
204
205 sys_put_le16(pan_id, pan_id_le);
206 memcpy(dev_pan_id, pan_id_le, PAN_ID_SIZE);
207
208 return 0;
209 }
210
upipe_set_short_addr(const struct device * dev,uint16_t short_addr)211 static int upipe_set_short_addr(const struct device *dev, uint16_t short_addr)
212 {
213 uint8_t short_addr_le[2];
214
215 ARG_UNUSED(dev);
216
217 sys_put_le16(short_addr, short_addr_le);
218 memcpy(dev_short_addr, short_addr_le, SHORT_ADDRESS_SIZE);
219
220 return 0;
221 }
222
upipe_set_ieee_addr(const struct device * dev,const uint8_t * ieee_addr)223 static int upipe_set_ieee_addr(const struct device *dev,
224 const uint8_t *ieee_addr)
225 {
226 ARG_UNUSED(dev);
227
228 memcpy(dev_ext_addr, ieee_addr, EXTENDED_ADDRESS_SIZE);
229
230 return 0;
231 }
232
upipe_filter(const struct device * dev,bool set,enum ieee802154_filter_type type,const struct ieee802154_filter * filter)233 static int upipe_filter(const struct device *dev,
234 bool set,
235 enum ieee802154_filter_type type,
236 const struct ieee802154_filter *filter)
237 {
238 LOG_DBG("Applying filter %u", type);
239
240 if (!set) {
241 return -ENOTSUP;
242 }
243
244 if (type == IEEE802154_FILTER_TYPE_IEEE_ADDR) {
245 return upipe_set_ieee_addr(dev, filter->ieee_addr);
246 } else if (type == IEEE802154_FILTER_TYPE_SHORT_ADDR) {
247 return upipe_set_short_addr(dev, filter->short_addr);
248 } else if (type == IEEE802154_FILTER_TYPE_PAN_ID) {
249 return upipe_set_pan_id(dev, filter->pan_id);
250 }
251
252 return -ENOTSUP;
253 }
254
upipe_set_txpower(const struct device * dev,int16_t dbm)255 static int upipe_set_txpower(const struct device *dev, int16_t dbm)
256 {
257 ARG_UNUSED(dev);
258 ARG_UNUSED(dbm);
259
260 return 0;
261 }
262
upipe_tx(const struct device * dev,enum ieee802154_tx_mode mode,struct net_pkt * pkt,struct net_buf * frag)263 static int upipe_tx(const struct device *dev,
264 enum ieee802154_tx_mode mode,
265 struct net_pkt *pkt,
266 struct net_buf *frag)
267 {
268 struct upipe_context *upipe = dev->data;
269 uint8_t *pkt_buf = frag->data;
270 uint8_t len = frag->len;
271 uint8_t i, data;
272
273 if (mode != IEEE802154_TX_MODE_DIRECT) {
274 NET_ERR("TX mode %d not supported", mode);
275 return -ENOTSUP;
276 }
277
278 LOG_DBG("%p (%u)", frag, len);
279
280 if (upipe->stopped) {
281 return -EIO;
282 }
283
284 data = UART_PIPE_RADIO_15_4_FRAME_TYPE;
285 uart_pipe_send(&data, 1);
286
287 data = len;
288 uart_pipe_send(&data, 1);
289
290 for (i = 0U; i < len; i++) {
291 uart_pipe_send(pkt_buf+i, 1);
292 }
293
294 return 0;
295 }
296
upipe_start(const struct device * dev)297 static int upipe_start(const struct device *dev)
298 {
299 struct upipe_context *upipe = dev->data;
300
301 if (!upipe->stopped) {
302 return -EALREADY;
303 }
304
305 upipe->stopped = false;
306
307 return 0;
308 }
309
upipe_stop(const struct device * dev)310 static int upipe_stop(const struct device *dev)
311 {
312 struct upipe_context *upipe = dev->data;
313
314 if (upipe->stopped) {
315 return -EALREADY;
316 }
317
318 upipe->stopped = true;
319
320 return 0;
321 }
322
323 /* driver-allocated attribute memory - constant across all driver instances */
324 IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
325
326 /* API implementation: attr_get */
upipe_attr_get(const struct device * dev,enum ieee802154_attr attr,struct ieee802154_attr_value * value)327 static int upipe_attr_get(const struct device *dev, enum ieee802154_attr attr,
328 struct ieee802154_attr_value *value)
329 {
330 ARG_UNUSED(dev);
331
332 return ieee802154_attr_get_channel_page_and_range(
333 attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
334 &drv_attr.phy_supported_channels, value);
335 }
336
upipe_init(const struct device * dev)337 static int upipe_init(const struct device *dev)
338 {
339 struct upipe_context *upipe = dev->data;
340
341 (void)memset(upipe, 0, sizeof(struct upipe_context));
342
343 uart_pipe_register(upipe->uart_pipe_buf, 1, upipe_rx);
344
345 upipe_stop(dev);
346
347 return 0;
348 }
349
get_mac(const struct device * dev)350 static inline uint8_t *get_mac(const struct device *dev)
351 {
352 struct upipe_context *upipe = dev->data;
353
354 upipe->mac_addr[0] = 0x00;
355 upipe->mac_addr[1] = 0x10;
356 upipe->mac_addr[2] = 0x20;
357 upipe->mac_addr[3] = 0x30;
358
359 #if defined(CONFIG_IEEE802154_UPIPE_RANDOM_MAC)
360 sys_rand_get(&upipe->mac_addr[4], 4U);
361 #else
362 upipe->mac_addr[4] = CONFIG_IEEE802154_UPIPE_MAC4;
363 upipe->mac_addr[5] = CONFIG_IEEE802154_UPIPE_MAC5;
364 upipe->mac_addr[6] = CONFIG_IEEE802154_UPIPE_MAC6;
365 upipe->mac_addr[7] = CONFIG_IEEE802154_UPIPE_MAC7;
366 #endif
367
368 return upipe->mac_addr;
369 }
370
upipe_iface_init(struct net_if * iface)371 static void upipe_iface_init(struct net_if *iface)
372 {
373 const struct device *dev = net_if_get_device(iface);
374 struct upipe_context *upipe = dev->data;
375 uint8_t *mac = get_mac(dev);
376
377 net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154);
378
379 upipe_dev = dev;
380 upipe->iface = iface;
381
382 ieee802154_init(iface);
383 }
384
385 static struct upipe_context upipe_context_data;
386
387 static const struct ieee802154_radio_api upipe_radio_api = {
388 .iface_api.init = upipe_iface_init,
389
390 .get_capabilities = upipe_get_capabilities,
391 .cca = upipe_cca,
392 .set_channel = upipe_set_channel,
393 .filter = upipe_filter,
394 .set_txpower = upipe_set_txpower,
395 .tx = upipe_tx,
396 .start = upipe_start,
397 .stop = upipe_stop,
398 .attr_get = upipe_attr_get,
399 };
400
401 NET_DEVICE_DT_INST_DEFINE(0, upipe_init, NULL, &upipe_context_data, NULL,
402 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &upipe_radio_api,
403 IEEE802154_L2, NET_L2_GET_CTX_TYPE(IEEE802154_L2),
404 IEEE802154_MTU);
405