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