1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_ieee802154_fake_driver, LOG_LEVEL_DBG);
9 
10 #include <zephyr/kernel.h>
11 
12 #include <zephyr/net/net_core.h>
13 #include <zephyr/net/net_if.h>
14 #include <zephyr/net/net_pkt.h>
15 
16 /** FAKE ieee802.15.4 driver **/
17 #include <zephyr/net/ieee802154_radio.h>
18 
19 #include "net_private.h"
20 #include <ieee802154_frame.h>
21 
22 struct net_pkt *current_pkt;
23 K_SEM_DEFINE(driver_lock, 0, UINT_MAX);
24 
25 uint8_t mock_ext_addr_be[8] = {0x00, 0x12, 0x4b, 0x00, 0x00, 0x9e, 0xa3, 0xc2};
26 
fake_get_capabilities(const struct device * dev)27 static enum ieee802154_hw_caps fake_get_capabilities(const struct device *dev)
28 {
29 	return IEEE802154_HW_FCS;
30 }
31 
fake_cca(const struct device * dev)32 static int fake_cca(const struct device *dev)
33 {
34 	return 0;
35 }
36 
fake_set_channel(const struct device * dev,uint16_t channel)37 static int fake_set_channel(const struct device *dev, uint16_t channel)
38 {
39 	NET_INFO("Channel %u", channel);
40 
41 	return 0;
42 }
43 
fake_set_txpower(const struct device * dev,int16_t dbm)44 static int fake_set_txpower(const struct device *dev, int16_t dbm)
45 {
46 	NET_INFO("TX power %d dbm", dbm);
47 
48 	return 0;
49 }
50 
insert_frag(struct net_pkt * pkt,struct net_buf * frag)51 static inline void insert_frag(struct net_pkt *pkt, struct net_buf *frag)
52 {
53 	struct net_buf *new_frag;
54 
55 	new_frag = net_pkt_get_frag(pkt, frag->len, K_SECONDS(1));
56 	if (!new_frag) {
57 		return;
58 	}
59 
60 	memcpy(new_frag->data, frag->data, frag->len);
61 	net_buf_add(new_frag, frag->len);
62 
63 	net_pkt_frag_add(current_pkt, new_frag);
64 }
65 
fake_tx(const struct device * dev,enum ieee802154_tx_mode mode,struct net_pkt * pkt,struct net_buf * frag)66 static int fake_tx(const struct device *dev,
67 		   enum ieee802154_tx_mode mode,
68 		   struct net_pkt *pkt,
69 		   struct net_buf *frag)
70 {
71 	NET_INFO("Sending packet %p - length %zu",
72 		 pkt, net_pkt_get_len(pkt));
73 
74 	if (!current_pkt) {
75 		return 0;
76 	}
77 
78 	insert_frag(pkt, frag);
79 
80 	if (ieee802154_is_ar_flag_set(frag)) {
81 		struct net_if *iface = net_if_lookup_by_dev(dev);
82 		struct ieee802154_context *ctx = net_if_l2_data(iface);
83 
84 		struct net_pkt *ack_pkt;
85 
86 		ack_pkt = net_pkt_rx_alloc_with_buffer(iface, IEEE802154_ACK_PKT_LENGTH, AF_UNSPEC,
87 						       0, K_FOREVER);
88 		if (!ack_pkt) {
89 			NET_ERR("*** Could not allocate ack pkt.");
90 			return -ENOMEM;
91 		}
92 
93 		if (!ieee802154_create_ack_frame(iface, ack_pkt, ctx->ack_seq)) {
94 			NET_ERR("*** Could not create ack frame.");
95 			net_pkt_unref(ack_pkt);
96 			return -EFAULT;
97 		}
98 
99 		ieee802154_handle_ack(iface, ack_pkt);
100 		net_pkt_unref(ack_pkt);
101 	}
102 
103 	k_sem_give(&driver_lock);
104 
105 	return 0;
106 }
107 
fake_start(const struct device * dev)108 static int fake_start(const struct device *dev)
109 {
110 	NET_INFO("FAKE ieee802154 driver started");
111 
112 	return 0;
113 }
114 
fake_stop(const struct device * dev)115 static int fake_stop(const struct device *dev)
116 {
117 	NET_INFO("FAKE ieee802154 driver stopped");
118 
119 	return 0;
120 }
121 
122 /* driver-allocated attribute memory - constant across all driver instances */
123 IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
124 
125 /* API implementation: attr_get */
fake_attr_get(const struct device * dev,enum ieee802154_attr attr,struct ieee802154_attr_value * value)126 static int fake_attr_get(const struct device *dev, enum ieee802154_attr attr,
127 			 struct ieee802154_attr_value *value)
128 {
129 	ARG_UNUSED(dev);
130 
131 	return ieee802154_attr_get_channel_page_and_range(
132 		attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
133 		&drv_attr.phy_supported_channels, value);
134 }
135 
fake_iface_init(struct net_if * iface)136 static void fake_iface_init(struct net_if *iface)
137 {
138 	struct ieee802154_context *ctx = net_if_l2_data(iface);
139 
140 	net_if_set_link_addr(iface, mock_ext_addr_be, 8, NET_LINK_IEEE802154);
141 
142 	ieee802154_init(iface);
143 
144 	ctx->pan_id = IEEE802154_PAN_ID_NOT_ASSOCIATED;
145 	ctx->short_addr = IEEE802154_SHORT_ADDRESS_NOT_ASSOCIATED;
146 	ctx->channel = 26U;
147 	ctx->sequence = 62U;
148 
149 	NET_INFO("FAKE ieee802154 iface initialized");
150 }
151 
fake_init(const struct device * dev)152 static int fake_init(const struct device *dev)
153 {
154 	fake_stop(dev);
155 
156 	return 0;
157 }
158 
159 static struct ieee802154_radio_api fake_radio_api = {
160 	.iface_api.init	= fake_iface_init,
161 
162 	.get_capabilities	= fake_get_capabilities,
163 	.cca			= fake_cca,
164 	.set_channel		= fake_set_channel,
165 	.set_txpower		= fake_set_txpower,
166 	.start			= fake_start,
167 	.stop			= fake_stop,
168 	.tx			= fake_tx,
169 	.attr_get		= fake_attr_get,
170 };
171 
172 NET_DEVICE_INIT(fake, "fake_ieee802154",
173 		fake_init, NULL, NULL, NULL,
174 		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
175 		&fake_radio_api, IEEE802154_L2,
176 		NET_L2_GET_CTX_TYPE(IEEE802154_L2), IEEE802154_MTU);
177