/* * Copyright (c) 2022 Trackunit Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include "modem_backend_mock.h" #include 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; }