640 lines
17 KiB
C
640 lines
17 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* mddp_sm.c - MDDP state machine.
|
|
*
|
|
* Copyright (c) 2020 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/slab.h>
|
|
#include <linux/mutex.h>
|
|
|
|
#include "mddp_ctrl.h"
|
|
#include "mddp_debug.h"
|
|
#include "mddp_filter.h"
|
|
#include "mddp_sm.h"
|
|
#include "mddp_usage.h"
|
|
#include "mddp_dev.h"
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Struct definition.
|
|
// -----------------------------------------------------------------------------
|
|
typedef int32_t (*mddp_sm_init_func_t)(struct mddp_app_t *app);
|
|
|
|
struct feature_set {
|
|
enum mddp_vc_mf_id_e type;
|
|
uint32_t bm; // bit map
|
|
};
|
|
|
|
struct check_feature_req {
|
|
uint16_t major_version;
|
|
uint16_t minor_version;
|
|
uint32_t wifi_feature;
|
|
};
|
|
|
|
struct check_feature_rsp {
|
|
uint16_t major_version;
|
|
uint16_t minor_version;
|
|
uint32_t num;
|
|
struct feature_set fs[0]; // Unfixed size
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Global variables.
|
|
//------------------------------------------------------------------------------
|
|
static const mddp_sm_init_func_t mddp_sm_init_func_list_s[] = {
|
|
#undef MDDP_MODULE_ID
|
|
#undef MDDP_MODULE_PREFIX
|
|
#define MDDP_MODULE_ID(_id)
|
|
#define MDDP_MODULE_PREFIX(_prefix) _prefix ## _sm_init,
|
|
#include "mddp_app_config.h"
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Private helper macro.
|
|
//------------------------------------------------------------------------------
|
|
#define MDDP_SM_LOCK_FLAG unsigned long flags
|
|
#define MDDP_SM_LOCK_INIT(_locker) spin_lock_init(&(_locker))
|
|
#define MDDP_SM_LOCK(_locker) spin_lock_irqsave(&(_locker), flags)
|
|
#define MDDP_SM_UNLOCK(_locker) spin_unlock_irqrestore(&(_locker), flags)
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Private variables.
|
|
//------------------------------------------------------------------------------
|
|
static struct mddp_app_t mddp_app_inst_s[MDDP_APP_TYPE_CNT];
|
|
static struct mutex mddp_state_handler_mtx;
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Private functions.
|
|
//------------------------------------------------------------------------------
|
|
static void _mddp_set_state(struct mddp_app_t *app, enum mddp_state_e new_state)
|
|
{
|
|
MDDP_SM_LOCK_FLAG;
|
|
|
|
MDDP_SM_LOCK(app->locker);
|
|
app->state = new_state;
|
|
MDDP_SM_UNLOCK(app->locker);
|
|
}
|
|
|
|
void mddp_check_feature(void)
|
|
{
|
|
struct mddp_md_msg_t *md_msg;
|
|
struct mddp_app_t *app;
|
|
struct check_feature_req ap_info = {
|
|
.major_version = 13,
|
|
.minor_version = 0,
|
|
.wifi_feature = 0
|
|
};
|
|
|
|
md_msg = kzalloc(sizeof(struct mddp_md_msg_t) + sizeof(struct check_feature_req),
|
|
GFP_ATOMIC);
|
|
if (unlikely(!md_msg)) {
|
|
MDDP_F_LOG(MDDP_LL_NOTICE,
|
|
"%s: failed to alloc md_msg bug!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
md_msg->msg_id = IPC_MSG_ID_MDFPM_CHECK_FEATURE_REQ;
|
|
md_msg->data_len = sizeof(struct check_feature_req);
|
|
app = mddp_get_app_inst(MDDP_APP_TYPE_WH);
|
|
app->abnormal_flags |= MDDP_ABNORMAL_CHECK_FEATURE_ABSENT;
|
|
memcpy(md_msg->data, &ap_info, md_msg->data_len);
|
|
mddp_ipc_send_md(app, md_msg, MDFPM_USER_ID_MDFPM);
|
|
}
|
|
|
|
static void mddp_handshake_done(void *buf, uint32_t buf_len)
|
|
{
|
|
struct mddp_app_t *app;
|
|
|
|
app = mddp_get_app_inst(MDDP_APP_TYPE_WH);
|
|
app->abnormal_flags &= ~MDDP_ABNORMAL_CHECK_FEATURE_ABSENT;
|
|
|
|
if (buf_len == 4) {
|
|
app->feature = *(uint32_t *)buf;
|
|
} else {
|
|
struct check_feature_rsp *rsp;
|
|
int i;
|
|
|
|
rsp = (struct check_feature_rsp *)buf;
|
|
if (buf_len == (8 + (rsp->num * 8))) {
|
|
app->feature |= MDDP_FEATURE_NEW_INFO;
|
|
app->mddp_feat.major_version = rsp->major_version;
|
|
app->mddp_feat.minor_version = rsp->minor_version;
|
|
for (i = 0; i < rsp->num; i++) {
|
|
switch (rsp->fs[i].type) {
|
|
case MF_ID_COMMON:
|
|
app->mddp_feat.common = rsp->fs[i].bm;
|
|
app->feature |= MDDP_FEATURE_MCIF_WIFI;
|
|
break;
|
|
case MF_ID_WFC:
|
|
app->mddp_feat.wfc = rsp->fs[i].bm;
|
|
app->feature |= MDDP_FEATURE_MCIF_WIFI;
|
|
break;
|
|
case MF_ID_MDDP_WH:
|
|
app->mddp_feat.wh = rsp->fs[i].bm;
|
|
app->feature |= MDDP_FEATURE_MDDP_WH;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} else
|
|
MDDP_S_LOG(MDDP_LL_ERR, "MD response size(%d) error, num(%d)",
|
|
buf_len, rsp->num);
|
|
}
|
|
}
|
|
|
|
bool mddp_check_subfeature(int type, int feat)
|
|
{
|
|
struct mddp_app_t *app;
|
|
|
|
app = mddp_get_app_inst(MDDP_APP_TYPE_WH);
|
|
switch (type) {
|
|
case MF_ID_COMMON:
|
|
return app->mddp_feat.common & (1 << feat);
|
|
case MF_ID_WFC:
|
|
return app->mddp_feat.wfc & (1 << feat);
|
|
case MF_ID_MDDP_WH:
|
|
return app->mddp_feat.wh & (1 << feat);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
char operate[4][14] = {
|
|
"Add dl filter",
|
|
"Del dl filter",
|
|
"Add ul filter",
|
|
"Del ul filter"
|
|
};
|
|
|
|
uint32_t printV4Msg(struct mdfpm_log *mdfpm_log_buf, int action_id_t, char *str_dstate)
|
|
{
|
|
uint32_t size;
|
|
uint16_t port[2];
|
|
char SrcAddr[16];
|
|
char DstAddr[16];
|
|
|
|
snprintf(SrcAddr, 16, "%3u.%3u.%3u.%3u",
|
|
mdfpm_log_buf->buf[0], mdfpm_log_buf->buf[1],
|
|
mdfpm_log_buf->buf[2], mdfpm_log_buf->buf[3]);
|
|
snprintf(DstAddr, 16, "%3u.%3u.%3u.%3u",
|
|
mdfpm_log_buf->buf[4], mdfpm_log_buf->buf[5],
|
|
mdfpm_log_buf->buf[6], mdfpm_log_buf->buf[7]);
|
|
port[0] = mdfpm_log_buf->buf[9] << 8 | mdfpm_log_buf->buf[8];
|
|
port[1] = mdfpm_log_buf->buf[11] << 8 | mdfpm_log_buf->buf[10];
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] %s, src_addr(%s), dst_addr(%s), src_port(%5u), dst_port(%5u)",
|
|
operate[action_id_t%4], SrcAddr, DstAddr, port[0], port[1]);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
return size;
|
|
}
|
|
|
|
uint32_t printV6Msg(struct mdfpm_log *mdfpm_log_buf, int action_id_t, char *str_dstate)
|
|
{
|
|
uint32_t idx, size;
|
|
uint16_t d16Addr[16], v6Port[2];
|
|
char v6SrcAddr[40];
|
|
char v6DstAddr[40];
|
|
|
|
for (idx = 0; idx < 16; idx++)
|
|
d16Addr[idx] = mdfpm_log_buf->buf[2*idx+1] << 8 | mdfpm_log_buf->buf[2*idx];
|
|
snprintf(v6SrcAddr, 40, "%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x",
|
|
d16Addr[0], d16Addr[1], d16Addr[2], d16Addr[3],
|
|
d16Addr[4], d16Addr[5], d16Addr[6], d16Addr[7]);
|
|
snprintf(v6DstAddr, 40, "%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x",
|
|
d16Addr[8], d16Addr[9], d16Addr[10], d16Addr[11],
|
|
d16Addr[12], d16Addr[13], d16Addr[14], d16Addr[15]);
|
|
v6Port[0] = mdfpm_log_buf->buf[33] << 8 | mdfpm_log_buf->buf[32];
|
|
v6Port[1] = mdfpm_log_buf->buf[35] << 8 | mdfpm_log_buf->buf[34];
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] %s, src_addr(%s), dst_addr(%s), src_port(%5u), dst_port(%5u)",
|
|
operate[action_id_t%4], v6SrcAddr, v6DstAddr, v6Port[0], v6Port[1]);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
return size;
|
|
}
|
|
|
|
uint32_t print_unexpected_id(struct mdfpm_log *mdfpm_log_buf, uint32_t buf_len, char *str_dstate)
|
|
{
|
|
uint32_t i, size, idx = 0;
|
|
char buffer[MDFPM_SEND_LOG_BUF_SZ];
|
|
|
|
for (i = 0; i < buf_len; i++)
|
|
idx += snprintf(&buffer[idx], buf_len-idx, "%u", mdfpm_log_buf->buf[i]);
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] Unexpected id, buffer:%s", buffer);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s\n", str_dstate);
|
|
return size;
|
|
}
|
|
|
|
static void mddp_print_mdfpm_log(struct mdfpm_log *buf, uint32_t buf_len)
|
|
{
|
|
uint32_t size = 0;
|
|
struct mdfpm_log *mdfpm_log_buf;
|
|
char str_dstate[MDFPM_SEND_LOG_BUF_SZ];
|
|
|
|
if (buf_len >= MDFPM_SEND_LOG_HEADER) {
|
|
mdfpm_log_buf = (struct mdfpm_log *)buf;
|
|
switch (mdfpm_log_buf->action_id) {
|
|
case MDFPM_LOG_NONE:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ, "[MDDP_WH] None");
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MDDP_WH_RUN:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ, "[MDDP_WH] Running");
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MDDP_WH_STOP:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ, "[MDDP_WH] Stopped");
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MDDP_EM_TEST:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] em_test_cmd_id(%u)",
|
|
mdfpm_log_buf->buf[0]);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MDDP_WH_LOCK_MD:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] Lock MD path(%u)",
|
|
mdfpm_log_buf->buf[0]);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MDDP_WH_RM_BY_REQ:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] Del filter by req, task_id(%u), level(%u)",
|
|
mdfpm_log_buf->buf[0], mdfpm_log_buf->buf[1]);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MDDP_WH_RM_BY_ASSIGN:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] Del filter by assign, level(%u)",
|
|
mdfpm_log_buf->buf[0]);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MDDP_WH_RM_BY_SCORE:
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] Del filter by score, level(%u)",
|
|
mdfpm_log_buf->buf[0]);
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "%s", str_dstate);
|
|
break;
|
|
case MDFPM_LOG_MD_ADD_FILTER_V4:
|
|
case MDFPM_LOG_MD_DEL_FILTER_V4:
|
|
case MDFPM_LOG_CS_ADD_FILTER_V4:
|
|
case MDFPM_LOG_CS_DEL_FILTER_V4:
|
|
size = printV4Msg(mdfpm_log_buf, mdfpm_log_buf->action_id, &str_dstate[0]);
|
|
break;
|
|
case MDFPM_LOG_MD_ADD_FILTER_V6:
|
|
case MDFPM_LOG_MD_DEL_FILTER_V6:
|
|
case MDFPM_LOG_CS_ADD_FILTER_V6:
|
|
case MDFPM_LOG_CS_DEL_FILTER_V6:
|
|
size = printV6Msg(mdfpm_log_buf, mdfpm_log_buf->action_id, &str_dstate[0]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (mdfpm_log_buf->action_id >= MDFPM_LOG_NUM)
|
|
size = print_unexpected_id(mdfpm_log_buf, buf_len, &str_dstate[0]);
|
|
} else {
|
|
size = snprintf(str_dstate, MDFPM_SEND_LOG_BUF_SZ,
|
|
"[MDDP_WH] error, buf_len(%u) should large than %u",
|
|
buf_len, MDFPM_SEND_LOG_HEADER);
|
|
MDDP_S_LOG(MDDP_LL_INFO, "%s", str_dstate);
|
|
}
|
|
mddp_enqueue_md_log(MDDP_MD_LOG_ID_GET_LOG, size, str_dstate);
|
|
}
|
|
|
|
static int32_t mddp_sm_ctrl_msg_hdlr(
|
|
uint32_t msg_id,
|
|
void *buf,
|
|
uint32_t buf_len)
|
|
{
|
|
int32_t ret = 0;
|
|
|
|
switch (msg_id) {
|
|
case IPC_MSG_ID_MDFPM_CHECK_FEATURE_RSP:
|
|
mddp_handshake_done(buf, buf_len);
|
|
break;
|
|
case IPC_MSG_ID_MDFPM_LOG:
|
|
mddp_print_mdfpm_log(buf, buf_len);
|
|
break;
|
|
default:
|
|
MDDP_S_LOG(MDDP_LL_ERR,
|
|
"%s: Unaccepted msg_id(%d)!\n",
|
|
__func__, msg_id);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Public functions.
|
|
//------------------------------------------------------------------------------
|
|
int32_t mddp_sm_init(void)
|
|
{
|
|
struct mddp_app_t *app;
|
|
uint32_t type;
|
|
uint32_t idx;
|
|
|
|
memset(&mddp_app_inst_s, 0, sizeof(mddp_app_inst_s));
|
|
|
|
for (idx = 0; idx < MDDP_MOD_CNT; idx++) {
|
|
type = mddp_sm_module_list_s[idx];
|
|
app = mddp_get_app_inst(type);
|
|
|
|
app->type = type;
|
|
MDDP_SM_LOCK_INIT(app->locker);
|
|
_mddp_set_state(app, MDDP_STATE_UNINIT);
|
|
|
|
mddp_sm_init_func_list_s[idx](app);
|
|
}
|
|
mutex_init(&mddp_state_handler_mtx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mddp_sm_uninit(void)
|
|
{
|
|
struct mddp_app_t *app;
|
|
uint32_t type;
|
|
uint32_t idx;
|
|
|
|
for (idx = 0; idx < MDDP_MOD_CNT; idx++) {
|
|
type = mddp_sm_module_list_s[idx];
|
|
app = mddp_get_app_inst(type);
|
|
|
|
mddp_sm_on_event(app, MDDP_EVT_FUNC_DISABLE);
|
|
}
|
|
|
|
memset(mddp_app_inst_s, 0, sizeof(mddp_app_inst_s));
|
|
}
|
|
|
|
struct mddp_app_t *mddp_get_default_app_inst(void)
|
|
{
|
|
return &mddp_app_inst_s[0];
|
|
}
|
|
|
|
struct mddp_app_t *mddp_get_app_inst(enum mddp_app_type_e type)
|
|
{
|
|
struct mddp_app_t *app;
|
|
|
|
app = &mddp_app_inst_s[type];
|
|
return app;
|
|
}
|
|
|
|
static enum mddp_state_e mddp_get_state(struct mddp_app_t *app)
|
|
{
|
|
return app->state;
|
|
}
|
|
|
|
enum mddp_state_e mddp_sm_set_state_by_md_rsp(struct mddp_app_t *app,
|
|
enum mddp_state_e prev_state,
|
|
bool md_rsp_result)
|
|
{
|
|
enum mddp_state_e curr_state;
|
|
enum mddp_state_e new_state = MDDP_STATE_DUMMY;
|
|
enum mddp_event_e event;
|
|
|
|
complete(&app->md_resp_comp);
|
|
curr_state = mddp_get_state(app);
|
|
event = (md_rsp_result) ? MDDP_EVT_MD_RSP_OK : MDDP_EVT_MD_RSP_FAIL;
|
|
|
|
if (curr_state == prev_state) {
|
|
/* OK.
|
|
* There is no interrupt event from upper module
|
|
* when MD handles this request.
|
|
*/
|
|
new_state = mddp_sm_on_event(app, event);
|
|
|
|
MDDP_S_LOG(MDDP_LL_NOTICE,
|
|
"%s: OK. event(%d), prev_state(%d) -> new_state(%d).\n",
|
|
__func__, event, prev_state, new_state);
|
|
|
|
return new_state;
|
|
}
|
|
|
|
/* DC (Don't Care).
|
|
* There are interrupt events from upper module
|
|
* when MD handles this request.
|
|
*/
|
|
MDDP_S_LOG(MDDP_LL_WARN,
|
|
"%s: DC. event(%d), prev_state(%d) -> new_state(%d).\n",
|
|
__func__, event, prev_state, new_state);
|
|
|
|
return MDDP_STATE_DUMMY;
|
|
}
|
|
|
|
#ifdef __MDDP_DEBUG__
|
|
void mddp_dump_sm_table(struct mddp_app_t *app)
|
|
{
|
|
uint32_t i, j;
|
|
struct mddp_sm_entry_t *state_machine;
|
|
struct mddp_sm_entry_t *entry;
|
|
|
|
MDDP_S_LOG(MDDP_LL_DEBUG,
|
|
"\n\n\t%s:\n==============================\n",
|
|
__func__);
|
|
|
|
for (i = 0; i < MDDP_STATE_CNT; i++) {
|
|
state_machine = app->state_machines[i];
|
|
MDDP_S_LOG(MDDP_LL_DEBUG, "\n=====(%d)=====\n", i);
|
|
|
|
for (j = 0; j < MDDP_EVT_CNT; j++) {
|
|
entry = state_machine + j;
|
|
|
|
if (entry->event == MDDP_EVT_DUMMY)
|
|
break;
|
|
|
|
MDDP_S_LOG(MDDP_LL_DEBUG,
|
|
"\tevt(%d), new_state(%d)\n",
|
|
entry->event, entry->new_state);
|
|
}
|
|
}
|
|
|
|
MDDP_S_LOG(MDDP_LL_DEBUG,
|
|
"\n ==============================\n\n");
|
|
}
|
|
#endif
|
|
|
|
enum mddp_state_e mddp_sm_on_event(struct mddp_app_t *app,
|
|
enum mddp_event_e event)
|
|
{
|
|
uint32_t idx;
|
|
enum mddp_state_e old_state;
|
|
enum mddp_state_e new_state;
|
|
struct mddp_sm_entry_t *state_machine;
|
|
struct mddp_sm_entry_t *entry;
|
|
|
|
mutex_lock(&mddp_state_handler_mtx);
|
|
|
|
new_state = old_state = mddp_get_state(app);
|
|
state_machine = app->state_machines[old_state];
|
|
|
|
for (idx = 0; idx < MDDP_EVT_CNT; idx++) {
|
|
entry = state_machine + idx;
|
|
if (event == entry->event) {
|
|
/*
|
|
* OK. Valid event for this state.
|
|
*/
|
|
new_state = entry->new_state;
|
|
|
|
if (new_state != MDDP_STATE_DUMMY)
|
|
_mddp_set_state(app, new_state);
|
|
|
|
mddp_dump_sm_table(app);
|
|
MDDP_S_LOG(MDDP_LL_WARN,
|
|
"%s: event(%d), old_state(%d) -> new_state(%d).\n",
|
|
__func__, event, old_state, new_state);
|
|
|
|
if (entry->action)
|
|
entry->action(app);
|
|
|
|
break;
|
|
} else if (entry->event == MDDP_EVT_DUMMY) {
|
|
/*
|
|
* NG. Unexpected event for this state!
|
|
*/
|
|
MDDP_S_LOG(MDDP_LL_WARN,
|
|
"%s: Invalid event(%d) for current state(%d)!\n",
|
|
__func__, event, old_state);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
mutex_unlock(&mddp_state_handler_mtx);
|
|
return new_state;
|
|
}
|
|
|
|
void mddp_sm_wait_pre(struct mddp_app_t *app)
|
|
{
|
|
init_completion(&app->md_resp_comp);
|
|
}
|
|
|
|
void mddp_sm_wait(struct mddp_app_t *app, enum mddp_event_e event)
|
|
{
|
|
enum mddp_state_e state;
|
|
|
|
state = mddp_get_state(app);
|
|
if ((state == MDDP_STATE_DISABLED) && (event != MDDP_EVT_FUNC_ENABLE))
|
|
return;
|
|
if ((state == MDDP_STATE_DEACTIVATED) && (event == MDDP_EVT_FUNC_DEACT))
|
|
return;
|
|
|
|
if (wait_for_completion_timeout(&app->md_resp_comp, msecs_to_jiffies(150)) == 0)
|
|
mddp_sm_on_event(app, MDDP_EVT_MD_RSP_TIMEOUT);
|
|
}
|
|
|
|
int32_t mddp_sm_msg_hdlr(
|
|
uint32_t user_id,
|
|
uint32_t msg_id,
|
|
void *buf,
|
|
uint32_t buf_len)
|
|
{
|
|
struct mddp_app_t *app = NULL;
|
|
int32_t ret = -ENODEV;
|
|
|
|
switch (user_id) {
|
|
case MDFPM_USER_ID_MDFPM:
|
|
ret = mddp_sm_ctrl_msg_hdlr(msg_id, buf, buf_len);
|
|
goto _done;
|
|
|
|
case MDFPM_USER_ID_WFPM:
|
|
app = mddp_get_app_inst(MDDP_APP_TYPE_WH);
|
|
break;
|
|
|
|
case MDFPM_USER_ID_DPFM:
|
|
ret = mddp_f_msg_hdlr(msg_id, buf, buf_len);
|
|
if (ret)
|
|
ret = mddp_u_msg_hdlr(msg_id, buf, buf_len);
|
|
|
|
goto _done;
|
|
|
|
default:
|
|
/*
|
|
* NG. Receive invalid ctrl_msg!
|
|
*/
|
|
MDDP_S_LOG(MDDP_LL_WARN,
|
|
"%s: Unaccepted user_id(%d)!\n",
|
|
__func__, user_id);
|
|
ret = -EINVAL;
|
|
goto _done;
|
|
}
|
|
|
|
/*
|
|
* OK. This app_type is configured.
|
|
*/
|
|
if (app && app->is_config) {
|
|
ret = app->md_recv_msg_hdlr(msg_id, buf, buf_len);
|
|
goto _done;
|
|
}
|
|
|
|
/*
|
|
* NG. This app_type is not configured!
|
|
*/
|
|
MDDP_S_LOG(MDDP_LL_ERR,
|
|
"%s: app is not configured, app(%p), user_id(%d), msg_id(%d)!\n",
|
|
__func__, app, user_id, msg_id);
|
|
|
|
_done:
|
|
return ret;
|
|
}
|
|
|
|
int32_t mddp_sm_reg_callback(
|
|
struct mddp_drv_conf_t *conf,
|
|
struct mddp_drv_handle_t *handle)
|
|
{
|
|
struct mddp_app_t *app;
|
|
|
|
app = mddp_get_app_inst(conf->app_type);
|
|
|
|
/*
|
|
* OK. This app_type is configured.
|
|
*/
|
|
if (app->is_config && app->reg_drv_callback) {
|
|
app->reg_drv_callback(handle);
|
|
memcpy(&app->drv_hdlr,
|
|
handle, sizeof(struct mddp_drv_handle_t));
|
|
app->drv_reg = 1;
|
|
app->abnormal_flags &= ~MDDP_ABNORMAL_WIFI_DRV_GET_FEATURE_BEFORE_MD_READY;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* NG. MDDP is not ready!
|
|
*/
|
|
MDDP_S_LOG(MDDP_LL_ERR,
|
|
"%s: Failed to reg callback, type(%d), config(%d)!\n",
|
|
__func__, conf->app_type, app->is_config);
|
|
return -EPERM;
|
|
}
|
|
|
|
void mddp_sm_dereg_callback(
|
|
struct mddp_drv_conf_t *conf,
|
|
struct mddp_drv_handle_t *handle)
|
|
{
|
|
struct mddp_app_t *app;
|
|
|
|
app = mddp_get_app_inst(conf->app_type);
|
|
|
|
/*
|
|
* OK. This app_type is configured.
|
|
*/
|
|
if (app->is_config && app->dereg_drv_callback) {
|
|
app->dereg_drv_callback(handle);
|
|
memset(&app->drv_hdlr,
|
|
0, sizeof(struct mddp_drv_handle_t));
|
|
app->drv_reg = 0;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* NG. MDDP is not ready!
|
|
*/
|
|
MDDP_S_LOG(MDDP_LL_ERR,
|
|
"%s: Failed to dereg callback, type(%d), config(%d)!\n",
|
|
__func__, conf->app_type, app->is_config);
|
|
return;
|
|
|
|
}
|