| /* | 
 |  * Copyright (c) 2022 Trackunit Corporation | 
 |  * | 
 |  * SPDX-License-Identifier: Apache-2.0 | 
 |  */ | 
 |  | 
 | #include <zephyr/modem/pipe.h> | 
 |  | 
 | #include <zephyr/logging/log.h> | 
 | LOG_MODULE_REGISTER(modem_pipe, CONFIG_MODEM_MODULES_LOG_LEVEL); | 
 |  | 
 | void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api *api) | 
 | { | 
 | 	__ASSERT_NO_MSG(pipe != NULL); | 
 | 	__ASSERT_NO_MSG(data != NULL); | 
 | 	__ASSERT_NO_MSG(api != NULL); | 
 |  | 
 | 	pipe->data = data; | 
 | 	pipe->api = api; | 
 | 	pipe->callback = NULL; | 
 | 	pipe->user_data = NULL; | 
 | 	pipe->state = MODEM_PIPE_STATE_CLOSED; | 
 | 	pipe->receive_ready_pending = false; | 
 |  | 
 | 	k_mutex_init(&pipe->lock); | 
 | 	k_condvar_init(&pipe->condvar); | 
 | } | 
 |  | 
 | int modem_pipe_open(struct modem_pipe *pipe) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	ret = pipe->api->open(pipe->data); | 
 |  | 
 | 	if (ret < 0) { | 
 | 		k_mutex_unlock(&pipe->lock); | 
 | 		return ret; | 
 | 	} | 
 |  | 
 | 	if (pipe->state == MODEM_PIPE_STATE_OPEN) { | 
 | 		k_mutex_unlock(&pipe->lock); | 
 | 		return 0; | 
 | 	} | 
 |  | 
 | 	k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000)); | 
 | 	ret = (pipe->state == MODEM_PIPE_STATE_OPEN) ? 0 : -EAGAIN; | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | int modem_pipe_open_async(struct modem_pipe *pipe) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	ret = pipe->api->open(pipe->data); | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback, void *user_data) | 
 | { | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	pipe->callback = callback; | 
 | 	pipe->user_data = user_data; | 
 |  | 
 | 	if (pipe->receive_ready_pending && (pipe->callback != NULL)) { | 
 | 		pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data); | 
 | 	} | 
 |  | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | } | 
 |  | 
 | int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 |  | 
 | 	if (pipe->state == MODEM_PIPE_STATE_CLOSED) { | 
 | 		k_mutex_unlock(&pipe->lock); | 
 | 		return -EPERM; | 
 | 	} | 
 |  | 
 | 	ret = pipe->api->transmit(pipe->data, buf, size); | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 |  | 
 | 	if (pipe->state == MODEM_PIPE_STATE_CLOSED) { | 
 | 		k_mutex_unlock(&pipe->lock); | 
 | 		return -EPERM; | 
 | 	} | 
 |  | 
 | 	ret = pipe->api->receive(pipe->data, buf, size); | 
 | 	pipe->receive_ready_pending = false; | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | void modem_pipe_release(struct modem_pipe *pipe) | 
 | { | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	pipe->callback = NULL; | 
 | 	pipe->user_data = NULL; | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | } | 
 |  | 
 | int modem_pipe_close(struct modem_pipe *pipe) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	ret = pipe->api->close(pipe->data); | 
 | 	if (ret < 0) { | 
 | 		k_mutex_unlock(&pipe->lock); | 
 | 		return ret; | 
 | 	} | 
 |  | 
 | 	if (pipe->state == MODEM_PIPE_STATE_CLOSED) { | 
 | 		k_mutex_unlock(&pipe->lock); | 
 | 		return 0; | 
 | 	} | 
 |  | 
 | 	k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000)); | 
 | 	ret = (pipe->state == MODEM_PIPE_STATE_CLOSED) ? 0 : -EAGAIN; | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | int modem_pipe_close_async(struct modem_pipe *pipe) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	ret = pipe->api->close(pipe->data); | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | void modem_pipe_notify_opened(struct modem_pipe *pipe) | 
 | { | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	pipe->state = MODEM_PIPE_STATE_OPEN; | 
 |  | 
 | 	if (pipe->callback != NULL) { | 
 | 		pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data); | 
 | 	} | 
 |  | 
 | 	k_condvar_signal(&pipe->condvar); | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | } | 
 |  | 
 | void modem_pipe_notify_closed(struct modem_pipe *pipe) | 
 | { | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 | 	pipe->state = MODEM_PIPE_STATE_CLOSED; | 
 | 	pipe->receive_ready_pending = false; | 
 |  | 
 | 	if (pipe->callback != NULL) { | 
 | 		pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data); | 
 | 	} | 
 |  | 
 | 	k_condvar_signal(&pipe->condvar); | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | } | 
 |  | 
 | void modem_pipe_notify_receive_ready(struct modem_pipe *pipe) | 
 | { | 
 | 	k_mutex_lock(&pipe->lock, K_FOREVER); | 
 |  | 
 | 	pipe->receive_ready_pending = true; | 
 |  | 
 | 	if (pipe->callback != NULL) { | 
 | 		pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data); | 
 | 	} | 
 |  | 
 | 	k_mutex_unlock(&pipe->lock); | 
 | } |