* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "apm_msg.h"
static int (* apm_msg_handler[APM_MSG_TYPE_MAX])(u32 udevid, struct apm_msg_header *header) = {NULL, };
static u32 apm_msg_len[APM_MSG_TYPE_MAX] = {0, };
void apm_register_msg_handle(enum apm_msg_type msg_type, u32 msg_len,
int (*fn)(u32 udevid, struct apm_msg_header *header))
{
apm_msg_handler[msg_type] = fn;
apm_msg_len[msg_type] = msg_len;
}
int apm_msg_recv(u32 udevid, void *data, u32 in_data_len, u32 out_data_len, u32 *real_out_len)
{
struct apm_msg_header *header = (struct apm_msg_header *)data;
if ((data == NULL) || (real_out_len == NULL)) {
apm_err("Null ptr. (udevid=%d)\n", udevid);
return -EINVAL;
}
if (in_data_len < sizeof(*header)) {
apm_err("Invalid len. (udevid=%d; in_data_len=%d; out_data_len=%d)\n", udevid, in_data_len, out_data_len);
return -EINVAL;
}
if ((header->msg_type < 0) || (header->msg_type >= APM_MSG_TYPE_MAX)) {
apm_err("Invalid msg_type. (udevid=%d; msg_type=%d)\n", udevid, header->msg_type);
return -EINVAL;
}
if (apm_msg_handler[header->msg_type] == NULL) {
apm_err("No msg handle. (udevid=%d; msg_type=%d)\n", udevid, header->msg_type);
return -EINVAL;
}
if ((in_data_len != apm_msg_len[header->msg_type]) || (out_data_len != apm_msg_len[header->msg_type])) {
apm_err("Invalid len. (udevid=%d; msg_type=%d; in_data_len=%d; out_data_len=%d; msg_len=%d)\n",
udevid, header->msg_type, in_data_len, out_data_len, apm_msg_len[header->msg_type]);
return -EINVAL;
}
*real_out_len = out_data_len;
header->result = apm_msg_handler[header->msg_type](udevid, header);
return 0;
}