blob: 60e877e44a34a873a010b72471a02497c67f6e76 [file] [log] [blame]
/*
* Copyright (c) 2022 Trackunit Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <zephyr/kernel.h>
#ifndef ZEPHYR_MODEM_PIPE_
#define ZEPHYR_MODEM_PIPE_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Modem Pipe
* @defgroup modem_pipe Modem Pipe
* @ingroup modem
* @{
*/
/** Modem pipe event */
enum modem_pipe_event {
MODEM_PIPE_EVENT_OPENED = 0,
MODEM_PIPE_EVENT_RECEIVE_READY,
MODEM_PIPE_EVENT_TRANSMIT_IDLE,
MODEM_PIPE_EVENT_CLOSED,
};
/**
* @cond INTERNAL_HIDDEN
*/
struct modem_pipe;
/**
* @endcond
*/
typedef void (*modem_pipe_api_callback)(struct modem_pipe *pipe, enum modem_pipe_event event,
void *user_data);
/**
* @cond INTERNAL_HIDDEN
*/
typedef int (*modem_pipe_api_open)(void *data);
typedef int (*modem_pipe_api_transmit)(void *data, const uint8_t *buf, size_t size);
typedef int (*modem_pipe_api_receive)(void *data, uint8_t *buf, size_t size);
typedef int (*modem_pipe_api_close)(void *data);
struct modem_pipe_api {
modem_pipe_api_open open;
modem_pipe_api_transmit transmit;
modem_pipe_api_receive receive;
modem_pipe_api_close close;
};
enum modem_pipe_state {
MODEM_PIPE_STATE_CLOSED = 0,
MODEM_PIPE_STATE_OPEN,
};
struct modem_pipe {
void *data;
struct modem_pipe_api *api;
modem_pipe_api_callback callback;
void *user_data;
enum modem_pipe_state state;
struct k_mutex lock;
struct k_condvar condvar;
uint8_t receive_ready_pending : 1;
uint8_t transmit_idle_pending : 1;
};
/**
* @brief Initialize a modem pipe
*
* @param pipe Pipe instance to initialize
* @param data Pipe data to bind to pipe instance
* @param api Pipe API implementation to bind to pipe instance
*/
void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api *api);
/**
* @endcond
*/
/**
* @brief Open pipe
*
* @param pipe Pipe instance
*
* @retval 0 if pipe was successfully opened or was already open
* @retval -errno code otherwise
*
* @warning Be cautious when using this synchronous version of the call.
* It may block the calling thread, which in the case of the system workqueue
* can result in a deadlock until this call times out waiting for the pipe to be open.
*/
int modem_pipe_open(struct modem_pipe *pipe);
/**
* @brief Open pipe asynchronously
*
* @param pipe Pipe instance
*
* @note The MODEM_PIPE_EVENT_OPENED event is invoked immediately if pipe is
* already opened.
*
* @retval 0 if pipe open was called successfully or pipe was already open
* @retval -errno code otherwise
*/
int modem_pipe_open_async(struct modem_pipe *pipe);
/**
* @brief Attach pipe to callback
*
* @param pipe Pipe instance
* @param callback Callback called when pipe event occurs
* @param user_data Free to use user data passed with callback
*
* @note The MODEM_PIPE_EVENT_RECEIVE_READY event is invoked immediately if pipe has pending
* data ready to receive.
*/
void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback, void *user_data);
/**
* @brief Transmit data through pipe
*
* @param pipe Pipe to transmit through
* @param buf Data to transmit
* @param size Number of bytes to transmit
*
* @retval Number of bytes placed in pipe
* @retval -EPERM if pipe is closed
* @retval -errno code on error
*
* @warning This call must be non-blocking
*/
int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size);
/**
* @brief Receive data through pipe
*
* @param pipe Pipe to receive from
* @param buf Destination for received data; must not be already in use in a modem module.
* @param size Capacity of destination for received data
*
* @retval Number of bytes received from pipe
* @retval -EPERM if pipe is closed
* @retval -errno code on error
*
* @warning This call must be non-blocking
*/
int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size);
/**
* @brief Clear callback
*
* @param pipe Pipe instance
*/
void modem_pipe_release(struct modem_pipe *pipe);
/**
* @brief Close pipe
*
* @param pipe Pipe instance
*
* @retval 0 if pipe open was called closed or pipe was already closed
* @retval -errno code otherwise
*
* @warning Be cautious when using this synchronous version of the call.
* It may block the calling thread, which in the case of the system workqueue
* can result in a deadlock until this call times out waiting for the pipe to be closed.
*/
int modem_pipe_close(struct modem_pipe *pipe);
/**
* @brief Close pipe asynchronously
*
* @param pipe Pipe instance
*
* @note The MODEM_PIPE_EVENT_CLOSED event is invoked immediately if pipe is
* already closed.
*
* @retval 0 if pipe close was called successfully or pipe was already closed
* @retval -errno code otherwise
*/
int modem_pipe_close_async(struct modem_pipe *pipe);
/**
* @cond INTERNAL_HIDDEN
*/
/**
* @brief Notify user of pipe that it has opened
*
* @param pipe Pipe instance
*
* @note Invoked from instance which initialized the pipe instance
*/
void modem_pipe_notify_opened(struct modem_pipe *pipe);
/**
* @brief Notify user of pipe that it has closed
*
* @param pipe Pipe instance
*
* @note Invoked from instance which initialized the pipe instance
*/
void modem_pipe_notify_closed(struct modem_pipe *pipe);
/**
* @brief Notify user of pipe that data is ready to be received
*
* @param pipe Pipe instance
*
* @note Invoked from instance which initialized the pipe instance
*/
void modem_pipe_notify_receive_ready(struct modem_pipe *pipe);
/**
* @brief Notify user of pipe that pipe has no more data to transmit
*
* @param pipe Pipe instance
*
* @note Invoked from instance which initialized the pipe instance
*/
void modem_pipe_notify_transmit_idle(struct modem_pipe *pipe);
/**
* @endcond
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_MODEM_PIPE_ */