blob: b8f461975a8305f2430b9c484427da5ca193b257 [file]
/*
* Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <errno.h>
#include <camkes/msgqueue_template.h>
#include <utils/util.h>
camkes_msgqueue_channel_t camkes_msgqueue_channels[MAX_CAMKES_MSGQUEUE_ID];
int num_registered_msgqueue_channels;
static inline int msgqueue_channel_check_common(int msgqueue_id, void *buffer, size_t buffer_size,
size_t message_size)
{
if (msgqueue_id >= MAX_CAMKES_MSGQUEUE_ID) {
ZF_LOGE("Supplied msgqueue_id is greater or equal to the maximum number of IDs");
return -EINVAL;
}
if (num_registered_msgqueue_channels >= MAX_CAMKES_MSGQUEUE_ID) {
ZF_LOGE("Trying to register more msgqueue channels than allowed");
return -EINVAL;
}
if (camkes_msgqueue_channels[msgqueue_id].role != MSGQUEUE_UNASSIGNED) {
ZF_LOGE("Trying to overwrite an initialised msgqueue channel");
return -EINVAL;
}
if (!buffer) {
ZF_LOGE("Trying to register a msgqueue channel with an empty buffer");
return -EINVAL;
}
if (message_size >= buffer_size) {
ZF_LOGE("The mesasage size of the channel is greater than the size of the buffer");
return -EINVAL;
}
return 0;
}
static inline void msgqueue_channel_init_common(int msgqueue_id, void *buffer, unsigned queue_len,
size_t buffer_size, size_t message_size)
{
camkes_msgqueue_channels[msgqueue_id] = (camkes_msgqueue_channel_t) {
0
};
camkes_msgqueue_channels[msgqueue_id].buffer = buffer;
camkes_msgqueue_channels[msgqueue_id].queue_len = queue_len;
camkes_msgqueue_channels[msgqueue_id].buffer_size = buffer_size;
camkes_msgqueue_channels[msgqueue_id].message_size = message_size;
}
int camkes_msgqueue_channel_register_sender(int msgqueue_id, void *buffer, unsigned queue_len,
size_t buffer_size, size_t message_size, void (*notify)(void))
{
int res = msgqueue_channel_check_common(msgqueue_id, buffer, buffer_size, message_size);
if (res) {
return res;
}
if (!notify) {
ZF_LOGE("Registering a sender msgqueue channel with empty 'notify' function pointer");
return -EINVAL;
}
msgqueue_channel_init_common(msgqueue_id, buffer, queue_len, buffer_size, message_size);
camkes_msgqueue_channels[msgqueue_id].role = MSGQUEUE_SENDER;
camkes_msgqueue_channels[msgqueue_id].sender_funcs.notify = notify;
return 0;
}
int camkes_msgqueue_channel_register_receiver(int msgqueue_id, void *buffer, unsigned queue_len,
size_t buffer_size, size_t message_size, int (*poll)(void), void (*wait)(void))
{
int res = msgqueue_channel_check_common(msgqueue_id, buffer, buffer_size, message_size);
if (res) {
return res;
}
if (!poll || !wait) {
ZF_LOGE("Registering a receiver msgqueue channel with empty 'poll' and 'wait' function pointers");
return -EINVAL;
}
msgqueue_channel_init_common(msgqueue_id, buffer, queue_len, buffer_size, message_size);
camkes_msgqueue_channels[msgqueue_id].role = MSGQUEUE_RECEIVER;
camkes_msgqueue_channels[msgqueue_id].receiver_funcs.poll = poll;
camkes_msgqueue_channels[msgqueue_id].receiver_funcs.wait = wait;
return 0;
}
camkes_msgqueue_channel_t *camkes_msgqueue_channel_get(int msgqueue_id, msgqueue_role_t role)
{
if (msgqueue_id >= MAX_CAMKES_MSGQUEUE_ID) {
ZF_LOGE("Trying to retrieve a channel with an ID greater than the maximum ID");
return NULL;
}
if (role == MSGQUEUE_UNASSIGNED) {
ZF_LOGE("Trying to retrieve an uninitialised channel");
return NULL;
}
if (camkes_msgqueue_channels[msgqueue_id].role != role) {
ZF_LOGE("Requested msgqueue channel doesn't match the role passed in");
return NULL;
}
return &camkes_msgqueue_channels[msgqueue_id];
}