初版
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".app_mode_manager.data.bss")
|
||||
#pragma data_seg(".app_mode_manager.data")
|
||||
#pragma const_seg(".app_mode_manager.text.const")
|
||||
#pragma code_seg(".app_mode_manager.text")
|
||||
#endif
|
||||
#include "app_mode_manager.h"
|
||||
#include "system/init.h"
|
||||
#include "generic/errno-base.h"
|
||||
|
||||
|
||||
|
||||
#define MODE_STACK_SIZE 2
|
||||
|
||||
|
||||
|
||||
struct app_mode_mgr {
|
||||
struct list_head head;
|
||||
struct list_head head2;
|
||||
struct app_mode *curr_mode;
|
||||
u8 mode_stack[MODE_STACK_SIZE];
|
||||
u8 stack_cnt;
|
||||
};
|
||||
|
||||
static struct app_mode_mgr g_mode_mgr;
|
||||
|
||||
#define for_each_app_mode(p) \
|
||||
list_for_each_entry(p, &g_mode_mgr.head, entry)
|
||||
|
||||
#define for_each_app_unactive_mode(p) \
|
||||
list_for_each_entry(p, &g_mode_mgr.head2, entry)
|
||||
|
||||
struct app_mode *app_get_current_mode()
|
||||
{
|
||||
return g_mode_mgr.curr_mode;
|
||||
}
|
||||
|
||||
|
||||
u8 app_get_current_mode_name()
|
||||
{
|
||||
if (g_mode_mgr.curr_mode) {
|
||||
return g_mode_mgr.curr_mode->name;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void app_set_current_mode(struct app_mode *mode)
|
||||
{
|
||||
g_mode_mgr.curr_mode = mode;
|
||||
}
|
||||
|
||||
struct app_mode *app_get_mode_by_name(u8 name)
|
||||
{
|
||||
struct app_mode *p;
|
||||
|
||||
for_each_app_mode(p) {
|
||||
if (p->name == name) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
for_each_app_unactive_mode(p) {
|
||||
if (p->name == name) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool app_have_mode(void)
|
||||
{
|
||||
if (g_mode_mgr.curr_mode) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool app_in_mode(u8 name)
|
||||
{
|
||||
if (g_mode_mgr.curr_mode) {
|
||||
return g_mode_mgr.curr_mode->name == name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct app_mode *app_next_mode(struct app_mode *mode)
|
||||
{
|
||||
struct list_head *next;
|
||||
|
||||
next = mode->entry.next;
|
||||
if (next == &g_mode_mgr.head) {
|
||||
next = g_mode_mgr.head.next;
|
||||
}
|
||||
return list_entry(next, struct app_mode, entry);
|
||||
}
|
||||
|
||||
struct app_mode *app_get_next_mode()
|
||||
{
|
||||
struct list_head *next;
|
||||
struct app_mode *p;
|
||||
bool current_mode_unactive = FALSE;
|
||||
|
||||
/*检查当前任务是否在unactive列表,如POWERON*/
|
||||
for_each_app_unactive_mode(p) {
|
||||
if (p->name == g_mode_mgr.curr_mode->name) {
|
||||
current_mode_unactive = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (current_mode_unactive) {
|
||||
next = g_mode_mgr.head.next;
|
||||
} else {
|
||||
next = g_mode_mgr.curr_mode->entry.next;
|
||||
}
|
||||
|
||||
if (next == &g_mode_mgr.head) {
|
||||
next = g_mode_mgr.head.next;
|
||||
}
|
||||
return list_entry(next, struct app_mode, entry);
|
||||
}
|
||||
|
||||
struct app_mode *app_get_prev_mode()
|
||||
{
|
||||
struct list_head *prev;
|
||||
|
||||
prev = g_mode_mgr.curr_mode->entry.prev;
|
||||
if (prev == &g_mode_mgr.head) {
|
||||
prev = g_mode_mgr.head.prev;
|
||||
}
|
||||
return list_entry(prev, struct app_mode, entry);
|
||||
}
|
||||
|
||||
int app_goto_next_mode(int param)
|
||||
{
|
||||
struct app_mode *mode = app_get_next_mode();
|
||||
return app_goto_mode(mode->name, param);
|
||||
}
|
||||
|
||||
int app_goto_prev_mode(int param)
|
||||
{
|
||||
struct app_mode *mode = app_get_prev_mode();
|
||||
return app_goto_mode(mode->name, param);
|
||||
}
|
||||
|
||||
int app_exit_mode(struct app_mode *mode)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!mode) {
|
||||
return 0;
|
||||
}
|
||||
if (mode->ops && mode->ops->try_exit) {
|
||||
err = mode->ops->try_exit();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (mode->ops && mode->ops->exit) {
|
||||
err = mode->ops->exit();
|
||||
}
|
||||
if (err == 0 && g_mode_mgr.curr_mode == mode) {
|
||||
g_mode_mgr.curr_mode = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int app_exit_current_mode()
|
||||
{
|
||||
return app_exit_mode(g_mode_mgr.curr_mode);
|
||||
}
|
||||
|
||||
bool app_try_exit_curr_mode()
|
||||
{
|
||||
struct app_mode *curr = g_mode_mgr.curr_mode;
|
||||
|
||||
if (curr && curr->ops && curr->ops->try_exit) {
|
||||
int err = curr->ops->try_exit();
|
||||
if (err) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool app_try_enter_mode(struct app_mode *mode, int param)
|
||||
{
|
||||
if (mode && mode->ops && mode->ops->try_enter) {
|
||||
int err = mode->ops->try_enter(param);
|
||||
if (err) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int app_goto_mode(u8 mode_name, int param)
|
||||
{
|
||||
int err = 0;
|
||||
struct app_mode *mode;
|
||||
struct app_mode *curr = g_mode_mgr.curr_mode;
|
||||
|
||||
if (curr) {
|
||||
if (curr->name == mode_name) {
|
||||
return 0;
|
||||
}
|
||||
if (curr->ops && curr->ops->try_exit) {
|
||||
err = curr->ops->try_exit();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mode = app_get_mode_by_name(mode_name);
|
||||
if (!mode) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode->ops && mode->ops->try_enter) {
|
||||
err = mode->ops->try_enter(param);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (curr && curr->ops && curr->ops->exit) {
|
||||
curr->ops->exit();
|
||||
}
|
||||
if (mode->ops && mode->ops->enter) {
|
||||
err = mode->ops->enter(param);
|
||||
}
|
||||
if (err == 0) {
|
||||
g_mode_mgr.curr_mode = mode;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int app_push_mode(u8 mode_name)
|
||||
{
|
||||
if (g_mode_mgr.stack_cnt < MODE_STACK_SIZE) {
|
||||
g_mode_mgr.mode_stack[g_mode_mgr.stack_cnt++] = mode_name;
|
||||
return 0;
|
||||
} else {
|
||||
if (g_mode_mgr.stack_cnt >= 2) {
|
||||
for (int i = 0; i < g_mode_mgr.stack_cnt - 2; i++) {
|
||||
g_mode_mgr.mode_stack[i] = g_mode_mgr.mode_stack[i + 1] ;
|
||||
}
|
||||
}
|
||||
g_mode_mgr.mode_stack[g_mode_mgr.stack_cnt - 1] = mode_name;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u8 app_pop_mode()
|
||||
{
|
||||
if (g_mode_mgr.stack_cnt) {
|
||||
return g_mode_mgr.mode_stack[--g_mode_mgr.stack_cnt];
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
u8 app_mode_stack_clr(u8 mode_name)
|
||||
{
|
||||
/* for(int i = 0;i<g_mode_mgr.stack_cnt ;i++){ */
|
||||
/* printf("%s [%d]task:%d stack_cnt:%d \n",__func__,i,g_mode_mgr.mode_stack[i],g_mode_mgr.stack_cnt); */
|
||||
/* } */
|
||||
for (int i = 0; i < g_mode_mgr.stack_cnt; i++) {
|
||||
if (g_mode_mgr.mode_stack[i] == mode_name) {
|
||||
for (int j = i; j < g_mode_mgr.stack_cnt; j++) { //仅对有效部分元素进行自加
|
||||
g_mode_mgr.mode_stack[j] = g_mode_mgr.mode_stack[j + 1];
|
||||
}
|
||||
--i;
|
||||
--g_mode_mgr.stack_cnt;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int app_goto_background(u8 mode_name)
|
||||
{
|
||||
int err = 0;
|
||||
struct app_mode *mode;
|
||||
|
||||
mode = app_get_mode_by_name(mode_name);
|
||||
if (!mode) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode->ops && mode->ops->goto_background) {
|
||||
err = mode->ops->goto_background();
|
||||
}
|
||||
if (err == 0 && g_mode_mgr.curr_mode == mode) {
|
||||
g_mode_mgr.curr_mode = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int app_goto_foreground(u8 mode_name)
|
||||
{
|
||||
int err = 0;
|
||||
struct app_mode *mode;
|
||||
|
||||
mode = app_get_mode_by_name(mode_name);
|
||||
if (!mode) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode->ops && mode->ops->goto_foreground) {
|
||||
err = mode->ops->goto_foreground();
|
||||
}
|
||||
if (err == 0) {
|
||||
g_mode_mgr.curr_mode = mode;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int app_mode_mgr_init()
|
||||
{
|
||||
struct app_mode *mode, *p;
|
||||
|
||||
g_mode_mgr.stack_cnt = 0;
|
||||
g_mode_mgr.curr_mode = NULL;
|
||||
INIT_LIST_HEAD(&g_mode_mgr.head);
|
||||
INIT_LIST_HEAD(&g_mode_mgr.head2);
|
||||
|
||||
list_for_each_app_mode(mode) {
|
||||
if (mode->index == 0xff) {
|
||||
list_add_tail(&mode->entry, &g_mode_mgr.head2);
|
||||
continue;
|
||||
}
|
||||
|
||||
int insert = 0;
|
||||
for_each_app_mode(p) {
|
||||
if (p->index > mode->index) {
|
||||
__list_add(&mode->entry, p->entry.prev, &p->entry);
|
||||
insert = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!insert) {
|
||||
list_add_tail(&mode->entry, &g_mode_mgr.head);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
early_initcall(app_mode_mgr_init);
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#ifndef APP_MODE_MANAGER_H
|
||||
#define APP_MODE_MANAGER_H
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "generic/list.h"
|
||||
|
||||
|
||||
struct app_mode_ops {
|
||||
int (*enter)(int param);
|
||||
int (*exit)();
|
||||
int (*try_enter)(int param);
|
||||
int (*try_exit)();
|
||||
int (*goto_background)();
|
||||
int (*goto_foreground)();
|
||||
int (*msg_handler)(int *msg);
|
||||
};
|
||||
|
||||
struct app_mode {
|
||||
u8 name;
|
||||
u8 index;
|
||||
u8 state;
|
||||
struct list_head entry;
|
||||
const struct app_mode_ops *ops;
|
||||
};
|
||||
|
||||
|
||||
#define REGISTER_APP_MODE(mode_name) \
|
||||
struct app_mode __##mode_name sec(.app_mode)
|
||||
|
||||
extern struct app_mode app_mode_begin[];
|
||||
extern struct app_mode app_mode_end[];
|
||||
|
||||
#define list_for_each_app_mode(mode) \
|
||||
for (mode = app_mode_begin; mode < app_mode_end; mode++)
|
||||
|
||||
|
||||
struct app_mode *app_get_current_mode();
|
||||
|
||||
extern u8 app_get_current_mode_name();
|
||||
|
||||
void app_set_current_mode(struct app_mode *mode);
|
||||
|
||||
struct app_mode *app_get_mode_by_name(u8 name);
|
||||
|
||||
bool app_have_mode(void);
|
||||
|
||||
bool app_in_mode(u8 name);
|
||||
|
||||
struct app_mode *app_next_mode(struct app_mode *mode);
|
||||
|
||||
struct app_mode *app_get_next_mode();
|
||||
|
||||
struct app_mode *app_get_prev_mode();
|
||||
|
||||
bool app_try_exit_curr_mode();
|
||||
|
||||
bool app_try_enter_mode(struct app_mode *mode, int param);
|
||||
|
||||
int app_goto_next_mode();
|
||||
|
||||
int app_goto_prev_mode();
|
||||
|
||||
int app_goto_mode(u8 mode_name, int param);
|
||||
|
||||
int app_push_mode(u8 mode_name);
|
||||
|
||||
int app_goto_foreground(u8 mode_name);
|
||||
|
||||
int app_goto_background(u8 mode_name);
|
||||
|
||||
u8 app_mode_stack_clr(u8 mode_name);
|
||||
|
||||
u8 app_pop_mode();
|
||||
|
||||
int app_exit_mode(struct app_mode *mode);
|
||||
|
||||
int app_exit_current_mode();
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user