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