1 /*
2  * Copyright (C) 2024 David Ullmann
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #define DT_DRV_COMPAT reyax_rylrxxx
12 
13 #include <zephyr/logging/log.h>
14 #include <zephyr/drivers/uart.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/drivers/lora.h>
18 #include <zephyr/modem/pipe.h>
19 #include <zephyr/modem/backend/uart.h>
20 #include <zephyr/modem/chat.h>
21 #include <zephyr/sys/atomic.h>
22 #include <errno.h>
23 
24 LOG_MODULE_REGISTER(rylr, CONFIG_LORA_LOG_LEVEL);
25 
26 #define RYLR_CMD_BAND_FORMAT                "AT+BAND=%u\r\n"
27 #define RYLR_CMD_BAND_PARM_CHARS            9U
28 #define RYLR_CMD_BAND_FORMAT_NUM_WILDCARDS  1U
29 #define RYLR_CMD_BAND_FORMAT_WILDCARD_CHARS (RYLR_CMD_BAND_FORMAT_NUM_WILDCARDS * 2)
30 #define RYLR_CMD_BAND_FORMAT_LEN_WITHOUT_WILDCARDS                                                 \
31 	(sizeof(RYLR_CMD_BAND_FORMAT) - RYLR_CMD_BAND_FORMAT_WILDCARD_CHARS - 1)
32 #define RYLR_CMD_BAND_LENGTH (RYLR_CMD_BAND_FORMAT_LEN_WITHOUT_WILDCARDS + RYLR_CMD_BAND_PARM_CHARS)
33 
34 #define RYLR_CMD_SEND_FORMAT                "AT+SEND=0,%u,%s\r\n"
35 #define RYLR_CMD_SEND_FORMAT_NUM_WILDCARDS  2U
36 #define RYLR_CMD_SEND_FORMAT_WILDCARD_CHARS (RYLR_CMD_SEND_FORMAT_NUM_WILDCARDS * 2)
37 #define RYLR_CMD_SEND_FORMAT_LEN_WITHOUT_WILDCARDS                                                 \
38 	(sizeof(RYLR_CMD_SEND_FORMAT) - RYLR_CMD_SEND_FORMAT_WILDCARD_CHARS - 1)
39 #define RYLR_PAYLOAD_LENGTH_FIELD_CHARS(payload_len)                                               \
40 	(payload_len >= 100 ? 3 : (payload_len >= 10 ? 2 : 1))
41 #define RYLR_CMD_SEND_LENGTH(payload_len)                                                          \
42 	(RYLR_CMD_SEND_FORMAT_LEN_WITHOUT_WILDCARDS +                                              \
43 	 RYLR_PAYLOAD_LENGTH_FIELD_CHARS(payload_len) + payload_len)
44 
45 #define RYLR_CMD_RF_SETTINGS_FORMAT                "AT+PARAMETER=%u,%u,%u,%u\r\n"
46 #define RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS  4U
47 #define RYLR_CMD_RF_SETTINGS_FORMAT_WILDCARD_CHARS (RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS * 2U)
48 #define RYLR_CMD_RF_SETTINGS_FORMAT_LEN_WITHOUT_WILDCARDS                                          \
49 	(sizeof(RYLR_CMD_RF_SETTINGS_FORMAT) - RYLR_CMD_RF_SETTINGS_FORMAT_WILDCARD_CHARS - 1)
50 #define RYLR_CMD_RF_SETTINGS_FORMAT_PARAM_CHARS(spread_factor)                                     \
51 	(RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS - 1) + (spread_factor >= 10U ? 2U : 1U)
52 #define RYLR_CMD_RF_SETTINGS_LEN(spread_factor)                                                    \
53 	(RYLR_CMD_RF_SETTINGS_FORMAT_LEN_WITHOUT_WILDCARDS +                                       \
54 	 RYLR_CMD_RF_SETTINGS_FORMAT_PARAM_CHARS(spread_factor))
55 
56 #define RYLR_CMD_POWER_FORMAT                "AT+CRFOP=%u\r\n"
57 #define RYLR_CMD_POWER_FORMAT_NUM_WILDCARDS  1U
58 #define RYLR_CMD_POWER_FORMAT_WILDCARD_CHARS (RYLR_CMD_POWER_FORMAT_NUM_WILDCARDS * 2U)
59 #define RYLR_CMD_POWER_FORMAT_LEN_WITHOUT_WILDCARDS                                                \
60 	(sizeof(RYLR_CMD_POWER_FORMAT) - RYLR_CMD_POWER_FORMAT_WILDCARD_CHARS - 1)
61 #define RYLR_CMD_POWER_FORMAT_PARAM_CHARS(power) (power >= 10U ? 2U : 1U)
62 #define RYLR_CMD_POWER_LEN(power)                                                                  \
63 	(RYLR_CMD_POWER_FORMAT_LEN_WITHOUT_WILDCARDS + RYLR_CMD_POWER_FORMAT_PARAM_CHARS(power))
64 
65 #define RYLR_MAX_RESPONSE  256
66 #define RYLR_MAX_MSG_BYTES 256
67 
68 #define RYLR_ALLOC_TIMEOUT K_SECONDS(1)
69 
70 #define RYLR_TX_PENDING_FLAG_POS (0U)
71 #define RYLR_RX_PENDING_FLAG_POS (1U)
72 
73 #define RYLR_IS_TX_PENDING(flags) (flags & (0x01 << RYLR_TX_PENDING_FLAG_POS))
74 #define RYLR_IS_RX_PENDING(flags) (flags & (0x01 << RYLR_RX_PENDING_FLAG_POS))
75 
76 #define RYLR_SET_TX_PENDING(flags) (flags |= (0x01 << RYLR_TX_PENDING_FLAG_POS))
77 #define RYLR_SET_RX_PENDING(flags) (flags |= (0x01 << RYLR_RX_PENDING_FLAG_POS))
78 
79 #define RYLR_CLEAR_TX_PENDING(flags) (flags &= ~(0x01 << RYLR_TX_PENDING_FLAG_POS))
80 #define RYLR_CLEAR_RX_PENDING(flags) (flags &= ~(0x01 << RYLR_RX_PENDING_FLAG_POS))
81 
82 #define RYLR_IS_ASYNC_OP_PENDING(flags) (RYLR_IS_RX_PENDING(flags) || RYLR_IS_TX_PENDING(flags))
83 
84 #define RYLR_MAX_RESPONSE_ARGS 6U
85 
86 #define RYLR_MIN_RESET_MSECS  (100U)
87 #define RYLR_RESET_WAIT_MSECS (RYLR_MIN_RESET_MSECS + 10U)
88 
89 struct rylr_config {
90 	const struct device *uart;
91 	const struct gpio_dt_spec reset;
92 };
93 
94 struct rylr_data {
95 	uint8_t cmd_buffer[CONFIG_LORA_RYLRXX_CMD_BUF_SIZE];
96 	size_t curr_cmd_len;
97 	bool is_tx;
98 	int handler_error;
99 	struct k_msgq rx_msgq;
100 	struct k_sem script_sem;
101 	struct k_sem operation_sem;
102 	uint8_t pending_async_flags;
103 	struct k_poll_signal *async_tx_signal;
104 	lora_recv_cb async_rx_cb;
105 	void *async_user_data;
106 	const struct device *dev;
107 	uint8_t msgq_buffer[CONFIG_RYLRXXX_UNSOLICITED_RX_MSGQ_SIZE];
108 	struct modem_pipe *modem_pipe;
109 	uint8_t uart_backend_rx_buff[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE];
110 	uint8_t uart_backend_tx_buff[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE];
111 	struct modem_pipe *uart_pipe;
112 	struct modem_backend_uart uart_backend;
113 	uint8_t chat_rx_buf[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE];
114 	uint8_t chat_tx_buf[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE];
115 	uint8_t *chat_argv[RYLR_MAX_RESPONSE_ARGS];
116 	struct modem_chat chat;
117 	struct modem_chat_script dynamic_script;
118 	struct modem_chat_script_chat dynamic_chat;
119 };
120 
121 struct rylr_recv_msg {
122 	uint16_t addr;
123 	uint8_t length;
124 	uint8_t *data;
125 	uint8_t rssi;
126 	uint8_t snr;
127 };
128 
on_ok(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)129 static void on_ok(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data)
130 {
131 	int err = 0;
132 	struct rylr_data *driver_data = user_data;
133 
134 	driver_data->handler_error = err;
135 }
136 
on_err(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)137 static void on_err(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data)
138 {
139 	int radio_err = 0;
140 	struct rylr_data *driver_data = user_data;
141 
142 	driver_data->handler_error = -EIO;
143 
144 	if (argc != 2) {
145 		driver_data->handler_error = -EBADMSG;
146 		LOG_ERR("malformed error message from radio");
147 		return;
148 	}
149 
150 	radio_err = atoi(argv[1]);
151 	LOG_ERR("error from rylr: %d", radio_err);
152 }
153 
on_rx(struct modem_chat * chat,char ** argv,uint16_t argc,void * user_data)154 static void on_rx(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data)
155 {
156 	struct rylr_data *driver_data = user_data;
157 	struct rylr_recv_msg msg;
158 	int err = 0;
159 
160 	driver_data->handler_error = 0;
161 
162 	if (argc != 6) {
163 		driver_data->handler_error = -EBADMSG;
164 		return;
165 	}
166 
167 	msg.addr = atoi(argv[1]);
168 	msg.length = atoi(argv[2]);
169 	msg.data = argv[3];
170 	msg.rssi = atoi(argv[4]);
171 	msg.snr = atoi(argv[5]);
172 
173 	if (RYLR_IS_RX_PENDING(driver_data->pending_async_flags)) {
174 		driver_data->async_rx_cb(driver_data->dev, msg.data, msg.length, msg.rssi, msg.snr,
175 					     driver_data->async_user_data);
176 	} else {
177 		err = k_msgq_put(&driver_data->rx_msgq, &msg, K_NO_WAIT);
178 		if (err != 0) {
179 			LOG_ERR("error adding messgae to queue: %d", err);
180 			driver_data->handler_error = err;
181 		}
182 	}
183 }
184 
on_script_finished(struct modem_chat * chat,enum modem_chat_script_result result,void * user_data)185 static void on_script_finished(struct modem_chat *chat, enum modem_chat_script_result result,
186 			       void *user_data)
187 {
188 	struct rylr_data *driver_data = user_data;
189 
190 	if (RYLR_IS_TX_PENDING(driver_data->pending_async_flags)) {
191 		RYLR_CLEAR_TX_PENDING(driver_data->pending_async_flags);
192 		k_poll_signal_raise(driver_data->async_tx_signal, driver_data->handler_error);
193 		k_sem_give(&driver_data->operation_sem);
194 	}
195 
196 	k_sem_give(&driver_data->script_sem);
197 }
198 
199 MODEM_CHAT_MATCH_DEFINE(ok_match, "+OK", "", on_ok);
200 
201 MODEM_CHAT_MATCHES_DEFINE(abort_matches, MODEM_CHAT_MATCH("+ERR=", "", on_err));
202 
203 MODEM_CHAT_MATCHES_DEFINE(unsol_matches, MODEM_CHAT_MATCH("+RCV=", ",", on_rx));
204 
205 MODEM_CHAT_SCRIPT_CMDS_DEFINE(ping_cmd, MODEM_CHAT_SCRIPT_CMD_RESP("AT\r\n", ok_match));
206 
207 MODEM_CHAT_SCRIPT_DEFINE(ping_script, ping_cmd, abort_matches, on_script_finished,
208 			 CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS);
209 
rylr_reset_dynamic_script(struct rylr_data * data)210 static void rylr_reset_dynamic_script(struct rylr_data *data)
211 {
212 	data->dynamic_chat.response_matches = &ok_match;
213 	data->dynamic_chat.response_matches_size = 1;
214 	data->dynamic_chat.timeout = 0;
215 
216 	data->dynamic_script.script_chats = &data->dynamic_chat;
217 	data->dynamic_script.script_chats_size = 1;
218 	data->dynamic_script.abort_matches = abort_matches;
219 	data->dynamic_script.abort_matches_size = 1;
220 	data->dynamic_script.callback = on_script_finished;
221 	data->dynamic_script.timeout = CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS;
222 }
223 
rylr_get_bandwidth_index(enum lora_signal_bandwidth bw)224 static uint32_t rylr_get_bandwidth_index(enum lora_signal_bandwidth bw)
225 {
226 	switch (bw) {
227 	case BW_125_KHZ:
228 		return 7;
229 	case BW_250_KHZ:
230 		return 8;
231 	case BW_500_KHZ:
232 		return 9;
233 	default:
234 		return 7;
235 	}
236 }
237 
rylr_send_cmd_buffer(const struct device * dev)238 static int rylr_send_cmd_buffer(const struct device *dev)
239 {
240 	int err = 0;
241 	struct rylr_data *data = dev->data;
242 
243 	rylr_reset_dynamic_script(data);
244 
245 	data->dynamic_chat.request = data->cmd_buffer;
246 	data->dynamic_chat.request_size = data->curr_cmd_len;
247 
248 	err = modem_chat_run_script(&data->chat, &data->dynamic_script);
249 	if (err != 0) {
250 		LOG_ERR("could not send cmd: %s. err: %d", data->cmd_buffer, err);
251 		return err;
252 	}
253 	err = k_sem_take(&data->script_sem, K_MSEC(CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS));
254 	if (err) {
255 		LOG_ERR("error waiting for response: %d", err);
256 		return err;
257 	}
258 	return data->handler_error;
259 }
260 
rylr_set_rf_band(const struct device * dev,uint32_t frequency)261 static int rylr_set_rf_band(const struct device *dev, uint32_t frequency)
262 {
263 	struct rylr_data *data = dev->data;
264 
265 	if (sprintf(data->cmd_buffer, RYLR_CMD_BAND_FORMAT, frequency) != RYLR_CMD_BAND_LENGTH) {
266 		LOG_ERR("could not create frequency string");
267 		return -EINVAL;
268 	}
269 
270 	data->curr_cmd_len = RYLR_CMD_BAND_LENGTH;
271 	return rylr_send_cmd_buffer(dev);
272 }
273 
rylr_set_rf_parameters(const struct device * dev,uint32_t datarate,uint32_t bandwidth,uint32_t coding_rate,uint32_t preamble_length)274 static int rylr_set_rf_parameters(const struct device *dev, uint32_t datarate, uint32_t bandwidth,
275 				  uint32_t coding_rate, uint32_t preamble_length)
276 {
277 	struct rylr_data *data = dev->data;
278 	size_t cmd_len;
279 
280 	if (datarate < 7 || datarate > 12) {
281 		LOG_ERR("datarate/spread factor must be between 7 and 12 inclusive");
282 		return -EINVAL;
283 	}
284 
285 	if (coding_rate < 1 || coding_rate > 4) {
286 		LOG_ERR("coding rate must be between 1 and 4 inclusive");
287 		return -EINVAL;
288 	}
289 
290 	if (preamble_length < 4 || preamble_length > 7) {
291 		LOG_ERR("preamble length must be between 4 and 7 inclusive");
292 		return -EINVAL;
293 	}
294 
295 	cmd_len = sprintf(data->cmd_buffer, RYLR_CMD_RF_SETTINGS_FORMAT, datarate,
296 			  rylr_get_bandwidth_index(bandwidth), coding_rate, preamble_length);
297 	if (cmd_len != RYLR_CMD_RF_SETTINGS_LEN(datarate)) {
298 		LOG_ERR("could not create rf settings string");
299 		return -EINVAL;
300 	}
301 
302 	data->curr_cmd_len = cmd_len;
303 	return rylr_send_cmd_buffer(dev);
304 }
305 
rylr_set_power(const struct device * dev,uint32_t power)306 static int rylr_set_power(const struct device *dev, uint32_t power)
307 {
308 	struct rylr_data *data = dev->data;
309 	size_t cmd_len;
310 
311 	if (power > 15) {
312 		LOG_ERR("power cannot be greater than 15");
313 		return -EINVAL;
314 	}
315 
316 	cmd_len = RYLR_CMD_POWER_LEN(power);
317 	if (sprintf(data->cmd_buffer, RYLR_CMD_POWER_FORMAT, power) != cmd_len) {
318 		LOG_ERR("could not create power string");
319 		return -EINVAL;
320 	}
321 
322 	data->curr_cmd_len = cmd_len;
323 	return rylr_send_cmd_buffer(dev);
324 }
325 
rylr_config(const struct device * dev,struct lora_modem_config * config)326 static int rylr_config(const struct device *dev, struct lora_modem_config *config)
327 {
328 	int err = 0;
329 	struct rylr_data *data = dev->data;
330 
331 	err = k_sem_take(&data->operation_sem, K_NO_WAIT);
332 	if (err != 0) {
333 		LOG_ERR("error taking operation semaphore: %d", err);
334 		return err;
335 	}
336 
337 	if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) {
338 		LOG_ERR("pending async opperation");
339 		err = -EBUSY;
340 		goto exit;
341 	}
342 
343 	err = rylr_set_rf_band(dev, config->frequency);
344 	if (err != 0) {
345 		LOG_ERR("could not send frequency cmd: %d", err);
346 		goto exit;
347 	}
348 
349 	err = rylr_set_rf_parameters(dev, config->datarate, config->bandwidth, config->coding_rate,
350 				     config->preamble_len);
351 	if (err != 0) {
352 		LOG_ERR("could not send rf params cmd: %d", err);
353 		goto exit;
354 	}
355 
356 	err = rylr_set_power(dev, config->tx_power);
357 	if (err != 0) {
358 		LOG_ERR("could not send power cmd: %d", err);
359 		goto exit;
360 	}
361 
362 	data->is_tx = config->tx;
363 
364 exit:
365 	k_sem_give(&data->operation_sem);
366 	return err;
367 }
368 
rylr_send(const struct device * dev,uint8_t * payload,uint32_t payload_len)369 int rylr_send(const struct device *dev, uint8_t *payload, uint32_t payload_len)
370 {
371 	int err = 0;
372 	struct rylr_data *data = dev->data;
373 	int cmd_len = RYLR_CMD_SEND_LENGTH(payload_len);
374 
375 	err = k_sem_take(&data->operation_sem, K_NO_WAIT);
376 	if (err != 0) {
377 		LOG_ERR("error taking operation semaphore: %d", err);
378 		return err;
379 	}
380 
381 	if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) {
382 		LOG_ERR("pending async opperation");
383 		err = -EBUSY;
384 		goto exit;
385 	}
386 
387 	if (!data->is_tx) {
388 		LOG_ERR("radio not configured in tx mode");
389 		err = -EOPNOTSUPP;
390 		goto exit;
391 	}
392 
393 	if (cmd_len > CONFIG_LORA_RYLRXX_CMD_BUF_SIZE) {
394 		LOG_ERR("payload too long");
395 		err = -EINVAL;
396 		goto exit;
397 	}
398 
399 	snprintf(data->cmd_buffer, cmd_len + 1, RYLR_CMD_SEND_FORMAT, payload_len, payload);
400 	data->curr_cmd_len = cmd_len;
401 	err = rylr_send_cmd_buffer(dev);
402 	if (err != 0) {
403 		LOG_ERR("error sending data: %d", err);
404 		goto exit;
405 	}
406 
407 exit:
408 	k_sem_give(&data->operation_sem);
409 	return err;
410 }
411 
rylr_send_async(const struct device * dev,uint8_t * payload,uint32_t payload_len,struct k_poll_signal * async)412 int rylr_send_async(const struct device *dev, uint8_t *payload, uint32_t payload_len,
413 		    struct k_poll_signal *async)
414 {
415 	int err = 0;
416 	struct rylr_data *data = dev->data;
417 	int cmd_len;
418 
419 	err = k_sem_take(&data->operation_sem, K_NO_WAIT);
420 	if (err != 0) {
421 		LOG_ERR("error taking operation sem: %d", err);
422 		return err;
423 	}
424 
425 	if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) {
426 		LOG_ERR("pending async opperation");
427 		err = -EBUSY;
428 		goto bail;
429 	}
430 
431 	RYLR_SET_TX_PENDING(data->pending_async_flags);
432 
433 	if (!data->is_tx) {
434 		LOG_ERR("radio not configured in tx mode");
435 		err = -EOPNOTSUPP;
436 		goto bail;
437 	}
438 
439 	cmd_len = RYLR_CMD_SEND_LENGTH(payload_len);
440 	if (cmd_len > CONFIG_LORA_RYLRXX_CMD_BUF_SIZE) {
441 		LOG_ERR("payload too long");
442 		err = -EINVAL;
443 		goto bail;
444 	}
445 
446 	if (async == NULL) {
447 		LOG_ERR("async signal cannot be null");
448 		err = -EINVAL;
449 		goto bail;
450 	}
451 
452 	data->async_tx_signal = async;
453 	data->curr_cmd_len =
454 		snprintf(data->cmd_buffer, cmd_len + 1, RYLR_CMD_SEND_FORMAT, payload_len, payload);
455 	rylr_reset_dynamic_script(data);
456 	data->dynamic_chat.request = data->cmd_buffer;
457 	data->dynamic_chat.request_size = data->curr_cmd_len;
458 
459 	return modem_chat_run_script_async(&data->chat, &data->dynamic_script);
460 bail:
461 	RYLR_CLEAR_TX_PENDING(data->pending_async_flags);
462 	k_sem_give(&data->operation_sem);
463 	return err;
464 }
465 
rylr_recv(const struct device * dev,uint8_t * ret_msg,uint8_t size,k_timeout_t timeout,int16_t * rssi,int8_t * snr)466 int rylr_recv(const struct device *dev, uint8_t *ret_msg, uint8_t size, k_timeout_t timeout,
467 	      int16_t *rssi, int8_t *snr)
468 {
469 
470 	int ret = 0;
471 	struct rylr_data *data = dev->data;
472 	struct rylr_recv_msg msg;
473 
474 	ret = k_sem_take(&data->operation_sem, K_NO_WAIT);
475 	if (ret != 0) {
476 		LOG_ERR("error taking operation semaphore: %d", ret);
477 		return ret;
478 	}
479 
480 	if (data->is_tx) {
481 		LOG_ERR("radio is configured for tx");
482 		ret = -EOPNOTSUPP;
483 		goto exit;
484 	}
485 
486 	if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) {
487 		LOG_ERR("pending async opperation");
488 		ret = -EBUSY;
489 		goto exit;
490 	}
491 
492 	ret = k_msgq_get(&data->rx_msgq, &msg, timeout);
493 	if (ret != 0) {
494 		LOG_ERR("error getting msg from queue: %d", ret);
495 		goto exit;
496 	}
497 
498 	ret = data->handler_error;
499 	if (ret != 0) {
500 		LOG_ERR("error in recv cb: %d", ret);
501 		goto exit;
502 	}
503 
504 	if (msg.length > size) {
505 		LOG_ERR("buf len of %u too small for message len of %u", size, msg.length);
506 		ret = -ENOBUFS;
507 		goto exit;
508 	}
509 
510 	*rssi = msg.rssi;
511 	*snr = msg.snr;
512 	memcpy(ret_msg, msg.data, msg.length);
513 	ret = msg.length;
514 
515 exit:
516 	k_sem_give(&data->operation_sem);
517 	return ret;
518 }
519 
rylr_recv_async(const struct device * dev,lora_recv_cb cb,void * user_data)520 int rylr_recv_async(const struct device *dev, lora_recv_cb cb, void *user_data)
521 {
522 	int err = 0;
523 	struct rylr_data *data = dev->data;
524 
525 	err = k_sem_take(&data->operation_sem, K_NO_WAIT);
526 	if (err != 0) {
527 		LOG_ERR("error taking operation semaphore: %d", err);
528 		return err;
529 	}
530 
531 	/* This is not a user error but the documeted way to cancel async reception in lora api*/
532 	if (cb == NULL) {
533 		goto bail;
534 	}
535 
536 	if (data->is_tx) {
537 		LOG_ERR("radio is configured for tx");
538 		err = -EOPNOTSUPP;
539 		goto bail;
540 	}
541 
542 	data->async_rx_cb = cb;
543 	data->async_user_data = user_data;
544 	if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) {
545 		LOG_ERR("pending async opperation");
546 		err = -EBUSY;
547 		goto bail;
548 	}
549 	RYLR_SET_RX_PENDING(data->pending_async_flags);
550 
551 	return err;
552 bail:
553 	RYLR_CLEAR_RX_PENDING(data->pending_async_flags);
554 	k_sem_give(&data->operation_sem);
555 	return err;
556 }
557 
rylr_test_cw(const struct device * dev,uint32_t frequency,int8_t tx_power,uint16_t duration)558 int rylr_test_cw(const struct device *dev, uint32_t frequency, int8_t tx_power, uint16_t duration)
559 {
560 	return -ENOSYS;
561 }
562 
rylr_init(const struct device * dev)563 static int rylr_init(const struct device *dev)
564 {
565 	int err = 0;
566 	struct rylr_data *data = dev->data;
567 	const struct rylr_config *config = dev->config;
568 
569 	if (!gpio_is_ready_dt(&config->reset)) {
570 		return -ENODEV;
571 	}
572 
573 	if (!device_is_ready(config->uart)) {
574 		return -ENODEV;
575 	}
576 
577 	err = gpio_pin_configure_dt(&config->reset, config->reset.dt_flags);
578 	if (err != 0) {
579 		LOG_ERR("error configuring reset gpio: %d", err);
580 		return err;
581 	}
582 
583 	k_msgq_init(&data->rx_msgq, data->msgq_buffer, sizeof(struct rylr_recv_msg),
584 		    ARRAY_SIZE(data->msgq_buffer));
585 
586 	err = k_sem_init(&data->script_sem, 0, 1);
587 	if (err != 0) {
588 		LOG_ERR("error initializing response semaphore. err=%d", err);
589 	}
590 
591 	err = k_sem_init(&data->operation_sem, 1, 1);
592 	if (err != 0) {
593 		LOG_ERR("error initializing operation semaphore. err=%d", err);
594 	}
595 
596 	const struct modem_backend_uart_config uart_backend_config = {
597 		.uart = config->uart,
598 		.receive_buf = data->uart_backend_rx_buff,
599 		.receive_buf_size = ARRAY_SIZE(data->uart_backend_rx_buff),
600 		.transmit_buf = data->uart_backend_tx_buff,
601 		.transmit_buf_size = ARRAY_SIZE(data->uart_backend_tx_buff),
602 	};
603 
604 	data->uart_pipe = modem_backend_uart_init(&data->uart_backend, &uart_backend_config);
605 
606 	const struct modem_chat_config chat_config = {
607 		.user_data = data,
608 		.receive_buf = data->chat_rx_buf,
609 		.receive_buf_size = ARRAY_SIZE(data->chat_rx_buf),
610 		.delimiter = "\r\n",
611 		.delimiter_size = sizeof("\r\n") - 1,
612 		.filter = NULL,
613 		.filter_size = 0,
614 		.argv = data->chat_argv,
615 		.argv_size = ARRAY_SIZE(data->chat_argv),
616 		.unsol_matches = unsol_matches,
617 		.unsol_matches_size = ARRAY_SIZE(unsol_matches),
618 	};
619 
620 	err = modem_chat_init(&data->chat, &chat_config);
621 	if (err != 0) {
622 		LOG_ERR("error initializing chat %d", err);
623 		return err;
624 	}
625 
626 	err = modem_chat_attach(&data->chat, data->uart_pipe);
627 	if (err != 0) {
628 		LOG_ERR("error attaching chat %d", err);
629 		return err;
630 	}
631 
632 	err = modem_pipe_open(data->uart_pipe, K_SECONDS(10));
633 	if (err != 0) {
634 		LOG_ERR("error opening uart pipe %d", err);
635 		return err;
636 	}
637 
638 	err = gpio_pin_set_dt(&config->reset, 1);
639 	if (err != 0) {
640 		LOG_ERR("error setting reset line: %d", err);
641 		return err;
642 	}
643 
644 	k_sleep(K_MSEC(RYLR_RESET_WAIT_MSECS));
645 
646 	err = gpio_pin_set_dt(&config->reset, 0);
647 	if (err != 0) {
648 		LOG_ERR("error unsetting reset line: %d", err);
649 		return err;
650 	}
651 
652 	k_sleep(K_MSEC(RYLR_RESET_WAIT_MSECS)); /* wait a bit more for module to boot up*/
653 
654 	err = modem_chat_run_script(&data->chat, &ping_script);
655 	if (err != 0) {
656 		LOG_ERR("error pinging radio: %d", err);
657 		return err;
658 	}
659 
660 	err = k_sem_take(&data->script_sem, K_MSEC(CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS));
661 	if (err != 0) {
662 		LOG_ERR("error waiting for ping response from radio %d", err);
663 		return err;
664 	}
665 
666 	LOG_INF("successfully initialized rylr");
667 	return err;
668 }
669 
670 static DEVICE_API(lora, rylr_lora_api) = {
671 	.config = rylr_config,
672 	.send = rylr_send,
673 	.send_async = rylr_send_async,
674 	.recv = rylr_recv,
675 	.recv_async = rylr_recv_async,
676 	.test_cw = rylr_test_cw,
677 };
678 
679 #define RYLR_DEVICE_INIT(n)                                                                        \
680 	static struct rylr_data dev_data_##n;                                                      \
681 	static const struct rylr_config dev_config_##n = {                                         \
682 		.uart = DEVICE_DT_GET(DT_INST_BUS(n)),                                             \
683 		.reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios),                                    \
684 	};                                                                                         \
685 	DEVICE_DT_INST_DEFINE(n, &rylr_init, NULL, &dev_data_##n, &dev_config_##n, POST_KERNEL,    \
686 			      CONFIG_LORA_INIT_PRIORITY, &rylr_lora_api);
687 
688 DT_INST_FOREACH_STATUS_OKAY(RYLR_DEVICE_INIT)
689