1 /*
2 * Copyright (c) 2024 A Labs GmbH
3 * Copyright (c) 2024 tado GmbH
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/lorawan/emul.h>
9 #include <zephyr/lorawan/lorawan.h>
10
11 #include <errno.h>
12
13 #include <LoRaMac.h>
14 #include <Region.h>
15
16 #include <zephyr/kernel.h>
17 #include <zephyr/init.h>
18 #include <zephyr/logging/log.h>
19
20 LOG_MODULE_REGISTER(lorawan_emul, CONFIG_LORAWAN_LOG_LEVEL);
21
22 static bool lorawan_adr_enable;
23
24 static sys_slist_t dl_callbacks;
25
26 static DeviceClass_t current_class;
27
28 static lorawan_battery_level_cb_t battery_level_cb;
29 static lorawan_dr_changed_cb_t dr_changed_cb;
30 static lorawan_uplink_cb_t uplink_cb;
31
32 /* implementation required by the soft-se (software secure element) */
BoardGetUniqueId(uint8_t * id)33 void BoardGetUniqueId(uint8_t *id)
34 {
35 /* Do not change the default value */
36 }
37
lorawan_emul_send_downlink(uint8_t port,bool data_pending,int16_t rssi,int8_t snr,uint8_t len,const uint8_t * data)38 void lorawan_emul_send_downlink(uint8_t port, bool data_pending, int16_t rssi, int8_t snr,
39 uint8_t len, const uint8_t *data)
40 {
41 struct lorawan_downlink_cb *cb;
42
43 /* Iterate over all registered downlink callbacks */
44 SYS_SLIST_FOR_EACH_CONTAINER(&dl_callbacks, cb, node) {
45 if ((cb->port == LW_RECV_PORT_ANY) || (cb->port == port)) {
46 cb->cb(port, data_pending, rssi, snr, len, data);
47 }
48 }
49 }
50
lorawan_join(const struct lorawan_join_config * join_cfg)51 int lorawan_join(const struct lorawan_join_config *join_cfg)
52 {
53 return 0;
54 }
55
lorawan_set_class(enum lorawan_class dev_class)56 int lorawan_set_class(enum lorawan_class dev_class)
57 {
58 switch (dev_class) {
59 case LORAWAN_CLASS_A:
60 current_class = CLASS_A;
61 break;
62 case LORAWAN_CLASS_B:
63 LOG_ERR("Class B not supported yet!");
64 return -ENOTSUP;
65 case LORAWAN_CLASS_C:
66 current_class = CLASS_C;
67 break;
68 default:
69 return -EINVAL;
70 }
71
72 return 0;
73 }
74
lorawan_set_datarate(enum lorawan_datarate dr)75 int lorawan_set_datarate(enum lorawan_datarate dr)
76 {
77 ARG_UNUSED(dr);
78
79 /* Bail out if using ADR */
80 if (lorawan_adr_enable) {
81 return -EINVAL;
82 }
83
84 return 0;
85 }
86
lorawan_get_payload_sizes(uint8_t * max_next_payload_size,uint8_t * max_payload_size)87 void lorawan_get_payload_sizes(uint8_t *max_next_payload_size, uint8_t *max_payload_size)
88 {
89 LoRaMacTxInfo_t tx_info;
90
91 /* QueryTxPossible cannot fail */
92 (void)LoRaMacQueryTxPossible(0, &tx_info);
93
94 *max_next_payload_size = tx_info.MaxPossibleApplicationDataSize;
95 *max_payload_size = tx_info.CurrentPossiblePayloadSize;
96 }
97
lorawan_get_min_datarate(void)98 enum lorawan_datarate lorawan_get_min_datarate(void)
99 {
100 return LORAWAN_DR_0;
101 }
102
lorawan_enable_adr(bool enable)103 void lorawan_enable_adr(bool enable)
104 {
105 lorawan_adr_enable = enable;
106 }
107
lorawan_set_conf_msg_tries(uint8_t tries)108 int lorawan_set_conf_msg_tries(uint8_t tries)
109 {
110 return 0;
111 }
112
lorawan_send(uint8_t port,uint8_t * data,uint8_t len,enum lorawan_message_type type)113 int lorawan_send(uint8_t port, uint8_t *data, uint8_t len, enum lorawan_message_type type)
114 {
115 if (data == NULL) {
116 return -EINVAL;
117 }
118
119 if (uplink_cb != NULL) {
120 uplink_cb(port, len, data);
121 }
122
123 return 0;
124 }
125
lorawan_register_battery_level_callback(lorawan_battery_level_cb_t cb)126 void lorawan_register_battery_level_callback(lorawan_battery_level_cb_t cb)
127 {
128 battery_level_cb = cb;
129 }
130
lorawan_register_downlink_callback(struct lorawan_downlink_cb * cb)131 void lorawan_register_downlink_callback(struct lorawan_downlink_cb *cb)
132 {
133 sys_slist_append(&dl_callbacks, &cb->node);
134 }
135
lorawan_register_dr_changed_callback(lorawan_dr_changed_cb_t cb)136 void lorawan_register_dr_changed_callback(lorawan_dr_changed_cb_t cb)
137 {
138 dr_changed_cb = cb;
139 }
140
lorawan_start(void)141 int lorawan_start(void)
142 {
143 return 0;
144 }
145
lorawan_init(void)146 static int lorawan_init(void)
147 {
148 sys_slist_init(&dl_callbacks);
149
150 return 0;
151 }
152
lorawan_emul_register_uplink_callback(lorawan_uplink_cb_t cb)153 void lorawan_emul_register_uplink_callback(lorawan_uplink_cb_t cb)
154 {
155 uplink_cb = cb;
156 }
157
158 SYS_INIT(lorawan_init, POST_KERNEL, 0);
159