1 /*
2  * Copyright (c) 2020 Manivannan Sadhasivam <mani@kernel.org>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_LORAWAN_LORAWAN_H_
8 #define ZEPHYR_INCLUDE_LORAWAN_LORAWAN_H_
9 
10 /**
11  * @file
12  * @brief Public LoRaWAN APIs
13  */
14 
15 #include <device.h>
16 #include <sys/slist.h>
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /**
23  * @brief LoRaWAN class types.
24  */
25 enum lorawan_class {
26 	LORAWAN_CLASS_A = 0x00,
27 	LORAWAN_CLASS_B = 0x01,
28 	LORAWAN_CLASS_C = 0x02,
29 };
30 
31 /**
32  * @brief LoRaWAN activation types.
33  */
34 enum lorawan_act_type {
35 	LORAWAN_ACT_OTAA = 0,
36 	LORAWAN_ACT_ABP,
37 };
38 
39 /**
40  * @brief LoRaWAN datarate types.
41  */
42 enum lorawan_datarate {
43 	LORAWAN_DR_0 = 0,
44 	LORAWAN_DR_1,
45 	LORAWAN_DR_2,
46 	LORAWAN_DR_3,
47 	LORAWAN_DR_4,
48 	LORAWAN_DR_5,
49 	LORAWAN_DR_6,
50 	LORAWAN_DR_7,
51 	LORAWAN_DR_8,
52 	LORAWAN_DR_9,
53 	LORAWAN_DR_10,
54 	LORAWAN_DR_11,
55 	LORAWAN_DR_12,
56 	LORAWAN_DR_13,
57 	LORAWAN_DR_14,
58 	LORAWAN_DR_15,
59 };
60 
61 /**
62  * @brief LoRaWAN message types.
63  *
64  * Note: The default message type is unconfirmed.
65  */
66 enum lorawan_message_type {
67 	LORAWAN_MSG_CONFIRMED = BIT(0),
68 };
69 
70 /**
71  * @brief LoRaWAN join parameters for over-the-Air activation (OTAA)
72  *
73  * Note that all of the fields use LoRaWAN 1.1 terminology.
74  *
75  * All parameters are optional if a secure element is present in which
76  * case the values stored in the secure element will be used instead.
77  */
78 struct lorawan_join_otaa {
79 	uint8_t *join_eui;
80 	uint8_t *nwk_key;
81 	uint8_t *app_key;
82 };
83 
84 struct lorawan_join_abp {
85 	/** Device address on the network */
86 	uint32_t dev_addr;
87 	/** Application session key */
88 	uint8_t *app_skey;
89 	/** Network session key */
90 	uint8_t *nwk_skey;
91 	/** Application EUI */
92 	uint8_t *app_eui;
93 };
94 
95 struct lorawan_join_config {
96 	union {
97 		struct lorawan_join_otaa otaa;
98 		struct lorawan_join_abp abp;
99 	};
100 
101 	/** Device EUI. Optional if a secure element is present. */
102 	uint8_t *dev_eui;
103 
104 	enum lorawan_act_type mode;
105 };
106 
107 #define LW_RECV_PORT_ANY UINT16_MAX
108 
109 struct lorawan_downlink_cb {
110 	/* Port to handle messages for:
111 	 *               Port 0: TX packet acknowledgements
112 	 *          Ports 1-255: Standard downlink port
113 	 *     LW_RECV_PORT_ANY: All downlinks
114 	 */
115 	uint16_t port;
116 	/**
117 	 * @brief Callback function to run on downlink data
118 	 *
119 	 * @note Callbacks are run on the system workqueue,
120 	 *       and should therefore be as short as possible.
121 	 *
122 	 * @param port Port message was sent on
123 	 * @param data_pending Network server has more downlink packets pending
124 	 * @param rssi Received signal strength in dBm
125 	 * @param snr Signal to Noise ratio in dBm
126 	 * @param len Length of data received, will be 0 for ACKs
127 	 * @param data Data received, will be NULL for ACKs
128 	 */
129 	void (*cb)(uint8_t port, bool data_pending,
130 		   int16_t rssi, int8_t snr,
131 		   uint8_t len, const uint8_t *data);
132 	/** Node for callback list */
133 	sys_snode_t node;
134 };
135 
136 /**
137  * @brief Add battery level callback function.
138  *
139  * Provide the LoRaWAN stack with a function to be called whenever a battery
140  * level needs to be read. As per LoRaWAN specification the callback needs to
141  * return "0:      node is connected to an external power source,
142  *         1..254: battery level, where 1 is the minimum and 254 is the maximum
143  *                 value,
144  *         255: the node was not able to measure the battery level"
145  *
146  * Should no callback be provided the lorawan backend will report 255.
147  *
148  * @param battery_lvl_cb Pointer to the battery level function
149  *
150  * @return 0 if successful, negative errno code if failure
151  */
152 int lorawan_set_battery_level_callback(uint8_t (*battery_lvl_cb)(void));
153 
154 /**
155  * @brief Register a callback to be run on downlink packets
156  *
157  * @param cb Pointer to structure containing callback parameters
158  */
159 void lorawan_register_downlink_callback(struct lorawan_downlink_cb *cb);
160 
161 /**
162  * @brief Register a callback to be called when the datarate changes
163  *
164  * The callback is called once upon successfully joining a network and again
165  * each time the datarate changes due to ADR.
166  *
167  * The callback function takes one parameter:
168  *	- dr - updated datarate
169  *
170  * @param dr_cb Pointer to datarate update callback
171  */
172 void lorawan_register_dr_changed_callback(void (*dr_cb)(enum lorawan_datarate));
173 
174 /**
175  * @brief Join the LoRaWAN network
176  *
177  * Join the LoRaWAN network using OTAA or AWB.
178  *
179  * @param config Configuration to be used
180  *
181  * @return 0 if successful, negative errno code if failure
182  */
183 int lorawan_join(const struct lorawan_join_config *config);
184 
185 /**
186  * @brief Start the LoRaWAN stack
187  *
188  * This function need to be called before joining the network.
189  *
190  * @return 0 if successful, negative errno code if failure
191  */
192 int lorawan_start(void);
193 
194 /**
195  * @brief Send data to the LoRaWAN network
196  *
197  * Send data to the connected LoRaWAN network.
198  *
199  * @param port       Port to be used for sending data. Must be set if the
200  *                   payload is not empty.
201  * @param data       Data buffer to be sent
202  * @param len        Length of the buffer to be sent. Maximum length of this
203  *                   buffer is 255 bytes but the actual payload size varies with
204  *                   region and datarate.
205  * @param flags      Flag used to determine the type of message being sent. It
206  *                   could be one of the lorawan_message_type. The default
207  *                   behaviour is unconfirmed message.
208  *
209  * @return 0 if successful, negative errno code if failure
210  */
211 int lorawan_send(uint8_t port, uint8_t *data, uint8_t len, uint8_t flags);
212 
213 /**
214  * @brief Set the current device class
215  *
216  * Change the current device class. This function may be called before
217  * or after a network connection has been established.
218  *
219  * @param dev_class New device class
220  *
221  * @return 0 if successful, negative errno code if failure
222  */
223 int lorawan_set_class(enum lorawan_class dev_class);
224 
225 /**
226  * @brief Set the number of tries used for transmissions
227  *
228  * @param tries Number of tries to be used
229  *
230  * @return 0 if successful, negative errno code if failure
231  */
232 int lorawan_set_conf_msg_tries(uint8_t tries);
233 
234 /**
235  * @brief Enable Adaptive Data Rate (ADR)
236  *
237  * Control whether adaptive data rate (ADR) is enabled. When ADR is enabled,
238  * the data rate is treated as a default data rate that will be used if the
239  * ADR algorithm has not established a data rate. ADR should normally only
240  * be enabled for devices with stable RF conditions (i.e., devices in a mostly
241  * static location).
242  *
243  * @param enable Enable or Disable adaptive data rate.
244  */
245 void lorawan_enable_adr(bool enable);
246 
247 /**
248  * @brief Set the default data rate
249  *
250  * Change the default data rate.
251  *
252  * @param dr Data rate used for transmissions
253  *
254  * @return 0 if successful, negative errno code if failure
255  */
256 int lorawan_set_datarate(enum lorawan_datarate dr);
257 
258 /**
259  * @brief Get the minimum possible datarate
260  *
261  * The minimum possible datarate may change in response to a TxParamSetupReq
262  * command from the network server.
263  *
264  * @return Minimum possible data rate
265  */
266 enum lorawan_datarate lorawan_get_min_datarate(void);
267 
268 /**
269  * @brief Get the current payload sizes
270  *
271  * Query the current payload sizes. The maximum payload size varies with
272  * datarate, while the current payload size can be less due to MAC layer
273  * commands which are inserted into uplink packets.
274  *
275  * @param max_next_payload_size Maximum payload size for the next transmission
276  * @param max_payload_size Maximum payload size for this datarate
277  */
278 void lorawan_get_payload_sizes(uint8_t *max_next_payload_size,
279 			       uint8_t *max_payload_size);
280 
281 #ifdef __cplusplus
282 }
283 #endif
284 
285 #endif /* ZEPHYR_INCLUDE_LORAWAN_LORAWAN_H_ */
286