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