Implements TRANSMIT_IDLE event notification for mock modem_pipe. Signed-off-by: Bjarki Arge Andreasen <bjarki@arge-andreasen.me>
158 lines
4.1 KiB
C
158 lines
4.1 KiB
C
/*
|
|
* Copyright (c) 2022 Trackunit Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include "modem_backend_mock.h"
|
|
|
|
#include <string.h>
|
|
|
|
static int modem_backend_mock_open(void *data)
|
|
{
|
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
|
|
|
modem_pipe_notify_opened(&mock->pipe);
|
|
return 0;
|
|
}
|
|
|
|
static bool modem_backend_mock_update(struct modem_backend_mock *mock, const uint8_t *buf,
|
|
size_t size)
|
|
{
|
|
if (mock->transaction == NULL) {
|
|
return false;
|
|
}
|
|
|
|
for (size_t i = 0; i < size; i++) {
|
|
__ASSERT(buf[i] == mock->transaction->get[mock->transaction_match_cnt],
|
|
"Unexpected transmit data");
|
|
|
|
mock->transaction_match_cnt++;
|
|
if (mock->transaction_match_cnt == mock->transaction->get_size) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static int modem_backend_mock_transmit(void *data, const uint8_t *buf, size_t size)
|
|
{
|
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
|
int ret;
|
|
|
|
size = (mock->limit < size) ? mock->limit : size;
|
|
|
|
if (mock->bridge) {
|
|
struct modem_backend_mock *t_mock = mock->bridge;
|
|
|
|
ret = ring_buf_put(&t_mock->rx_rb, buf, size);
|
|
k_work_submit(&t_mock->receive_ready_work);
|
|
k_work_submit(&mock->transmit_idle_work);
|
|
return ret;
|
|
}
|
|
|
|
ret = ring_buf_put(&mock->tx_rb, buf, size);
|
|
if (modem_backend_mock_update(mock, buf, size)) {
|
|
modem_backend_mock_put(mock, mock->transaction->put,
|
|
mock->transaction->put_size);
|
|
|
|
mock->transaction = NULL;
|
|
}
|
|
|
|
k_work_submit(&mock->transmit_idle_work);
|
|
return ret;
|
|
}
|
|
|
|
static int modem_backend_mock_receive(void *data, uint8_t *buf, size_t size)
|
|
{
|
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
|
|
|
size = (mock->limit < size) ? mock->limit : size;
|
|
return ring_buf_get(&mock->rx_rb, buf, size);
|
|
}
|
|
|
|
static int modem_backend_mock_close(void *data)
|
|
{
|
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
|
|
|
modem_pipe_notify_closed(&mock->pipe);
|
|
return 0;
|
|
}
|
|
|
|
struct modem_pipe_api modem_backend_mock_api = {
|
|
.open = modem_backend_mock_open,
|
|
.transmit = modem_backend_mock_transmit,
|
|
.receive = modem_backend_mock_receive,
|
|
.close = modem_backend_mock_close,
|
|
};
|
|
|
|
static void modem_backend_mock_receive_ready_handler(struct k_work *item)
|
|
{
|
|
struct modem_backend_mock *mock =
|
|
CONTAINER_OF(item, struct modem_backend_mock, receive_ready_work);
|
|
|
|
modem_pipe_notify_receive_ready(&mock->pipe);
|
|
}
|
|
|
|
static void modem_backend_mock_transmit_idle_handler(struct k_work *item)
|
|
{
|
|
struct modem_backend_mock *mock =
|
|
CONTAINER_OF(item, struct modem_backend_mock, transmit_idle_work);
|
|
|
|
modem_pipe_notify_transmit_idle(&mock->pipe);
|
|
}
|
|
|
|
struct modem_pipe *modem_backend_mock_init(struct modem_backend_mock *mock,
|
|
const struct modem_backend_mock_config *config)
|
|
{
|
|
memset(mock, 0, sizeof(*mock));
|
|
|
|
ring_buf_init(&mock->rx_rb, config->rx_buf_size, config->rx_buf);
|
|
ring_buf_init(&mock->tx_rb, config->tx_buf_size, config->tx_buf);
|
|
k_work_init(&mock->receive_ready_work, modem_backend_mock_receive_ready_handler);
|
|
k_work_init(&mock->transmit_idle_work, modem_backend_mock_transmit_idle_handler);
|
|
mock->limit = config->limit;
|
|
modem_pipe_init(&mock->pipe, mock, &modem_backend_mock_api);
|
|
return &mock->pipe;
|
|
}
|
|
|
|
struct modem_pipe *modem_backend_mock_get_pipe(struct modem_backend_mock *mock)
|
|
{
|
|
return &mock->pipe;
|
|
}
|
|
|
|
void modem_backend_mock_reset(struct modem_backend_mock *mock)
|
|
{
|
|
ring_buf_reset(&mock->rx_rb);
|
|
ring_buf_reset(&mock->tx_rb);
|
|
mock->transaction = NULL;
|
|
mock->transaction_match_cnt = 0;
|
|
}
|
|
|
|
int modem_backend_mock_get(struct modem_backend_mock *mock, uint8_t *buf, size_t size)
|
|
{
|
|
return ring_buf_get(&mock->tx_rb, buf, size);
|
|
}
|
|
|
|
void modem_backend_mock_put(struct modem_backend_mock *mock, const uint8_t *buf, size_t size)
|
|
{
|
|
__ASSERT(ring_buf_put(&mock->rx_rb, buf, size) == size,
|
|
"Mock buffer capacity exceeded");
|
|
|
|
k_work_submit(&mock->receive_ready_work);
|
|
}
|
|
|
|
void modem_backend_mock_prime(struct modem_backend_mock *mock,
|
|
const struct modem_backend_mock_transaction *transaction)
|
|
{
|
|
mock->transaction = transaction;
|
|
mock->transaction_match_cnt = 0;
|
|
}
|
|
|
|
void modem_backend_mock_bridge(struct modem_backend_mock *mock_a, struct modem_backend_mock *mock_b)
|
|
{
|
|
mock_a->bridge = mock_b;
|
|
mock_b->bridge = mock_a;
|
|
}
|