| /* |
| * Copyright (c) 2014, Mentor Graphics Corporation |
| * Copyright (c) 2015 Xilinx, Inc. |
| * Copyright (c) 2016 Freescale Semiconductor, Inc. |
| * Copyright 2016-2019 NXP |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| #include "rpmsg_lite.h" |
| #include "rpmsg_queue.h" |
| |
| typedef struct |
| { |
| uint32_t src; |
| void *data; |
| uint32_t len; |
| } rpmsg_queue_rx_cb_data_t; |
| |
| int32_t rpmsg_queue_rx_cb(void *payload, uint32_t payload_len, uint32_t src, void *priv) |
| { |
| rpmsg_queue_rx_cb_data_t msg; |
| |
| RL_ASSERT(priv != RL_NULL); |
| |
| msg.data = payload; |
| msg.len = payload_len; |
| msg.src = src; |
| |
| /* if message is successfully added into queue then hold rpmsg buffer */ |
| if (0 != env_put_queue(priv, &msg, 0)) |
| { |
| /* hold the rx buffer */ |
| return RL_HOLD; |
| } |
| |
| return RL_RELEASE; |
| } |
| |
| rpmsg_queue_handle rpmsg_queue_create(struct rpmsg_lite_instance *rpmsg_lite_dev) |
| { |
| int32_t status; |
| void *q = RL_NULL; |
| |
| if (rpmsg_lite_dev == RL_NULL) |
| { |
| return RL_NULL; |
| } |
| |
| /* create message queue for channel default endpoint */ |
| status = env_create_queue(&q, (int32_t)rpmsg_lite_dev->rvq->vq_nentries, (int32_t)sizeof(rpmsg_queue_rx_cb_data_t)); |
| if ((status != 0) || (q == RL_NULL)) |
| { |
| return RL_NULL; |
| } |
| |
| return ((rpmsg_queue_handle)q); |
| } |
| |
| int32_t rpmsg_queue_destroy(struct rpmsg_lite_instance *rpmsg_lite_dev, rpmsg_queue_handle q) |
| { |
| if (rpmsg_lite_dev == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| |
| if (q == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| env_delete_queue((void *)q); |
| return RL_SUCCESS; |
| } |
| |
| int32_t rpmsg_queue_recv(struct rpmsg_lite_instance *rpmsg_lite_dev, |
| rpmsg_queue_handle q, |
| uint32_t *src, |
| char *data, |
| uint32_t maxlen, |
| uint32_t *len, |
| uint32_t timeout) |
| { |
| rpmsg_queue_rx_cb_data_t msg = {0}; |
| int32_t retval = RL_SUCCESS; |
| |
| if (rpmsg_lite_dev == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| if (q == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| if (data == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| |
| /* Get an element out of the message queue for the selected endpoint */ |
| if (0 != env_get_queue((void *)q, &msg, timeout)) |
| { |
| if (src != RL_NULL) |
| { |
| *src = msg.src; |
| } |
| if (len != RL_NULL) |
| { |
| *len = msg.len; |
| } |
| |
| if (maxlen >= msg.len) |
| { |
| env_memcpy(data, msg.data, msg.len); |
| } |
| else |
| { |
| retval = RL_ERR_BUFF_SIZE; |
| } |
| |
| /* Release used buffer. */ |
| return ((RL_SUCCESS == rpmsg_lite_release_rx_buffer(rpmsg_lite_dev, msg.data)) ? retval : RL_ERR_PARAM); |
| } |
| else |
| { |
| return RL_ERR_NO_BUFF; /* failed */ |
| } |
| } |
| |
| int32_t rpmsg_queue_recv_nocopy(struct rpmsg_lite_instance *rpmsg_lite_dev, |
| rpmsg_queue_handle q, |
| uint32_t *src, |
| char **data, |
| uint32_t *len, |
| uint32_t timeout) |
| { |
| rpmsg_queue_rx_cb_data_t msg = {0}; |
| |
| if (rpmsg_lite_dev == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| if (data == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| if (q == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| |
| /* Get an element out of the message queue for the selected endpoint */ |
| if (0 != env_get_queue((void *)q, &msg, timeout)) |
| { |
| if (src != RL_NULL) |
| { |
| *src = msg.src; |
| } |
| if (len != RL_NULL) |
| { |
| *len = msg.len; |
| } |
| |
| *data = msg.data; |
| |
| return RL_SUCCESS; /* success */ |
| } |
| |
| return RL_ERR_NO_BUFF; /* failed */ |
| } |
| |
| int32_t rpmsg_queue_nocopy_free(struct rpmsg_lite_instance *rpmsg_lite_dev, void *data) |
| { |
| if (rpmsg_lite_dev == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| if (data == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| |
| /* Release used buffer. */ |
| return ((RL_SUCCESS == rpmsg_lite_release_rx_buffer(rpmsg_lite_dev, data)) ? RL_SUCCESS : RL_ERR_PARAM); |
| } |
| |
| int32_t rpmsg_queue_get_current_size(rpmsg_queue_handle q) |
| { |
| if (q == RL_NULL) |
| { |
| return RL_ERR_PARAM; |
| } |
| |
| /* Return actual queue size. */ |
| return env_get_current_queue_size((void *)q); |
| } |