1 /*
2  * Copyright (c) 2023 Fabian Blatz <fabianblatz@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/shell/shell.h>
8 #include <lvgl.h>
9 #include <zephyr/autoconf.h>
10 
11 #ifdef CONFIG_LV_Z_MEM_POOL_SYS_HEAP
12 #include "lvgl_mem.h"
13 #endif
14 
15 #ifdef CONFIG_LV_USE_MONKEY
16 static lv_monkey_t *lvgl_monkeys[CONFIG_LV_Z_MAX_MONKEY_COUNT];
17 
lvgl_monkey_indev_as_string(lv_monkey_t * monkey)18 static const char *lvgl_monkey_indev_as_string(lv_monkey_t *monkey)
19 {
20 	lv_indev_t *input_device;
21 
22 	input_device = lv_monkey_get_indev(monkey);
23 	if (!input_device) {
24 		return "unknown";
25 	}
26 
27 	switch (lv_indev_get_type(input_device)) {
28 	case LV_INDEV_TYPE_POINTER:
29 		return "pointer";
30 	case LV_INDEV_TYPE_KEYPAD:
31 		return "keypad";
32 	case LV_INDEV_TYPE_BUTTON:
33 		return "button";
34 	case LV_INDEV_TYPE_ENCODER:
35 		return "encoder";
36 	default:
37 		return "unknown";
38 	}
39 }
40 
lvgl_monkey_indev_from_string(const char * str,lv_indev_type_t * input_device)41 static int lvgl_monkey_indev_from_string(const char *str, lv_indev_type_t *input_device)
42 {
43 	if (strcmp(str, "pointer") == 0) {
44 		*input_device = LV_INDEV_TYPE_POINTER;
45 	} else if (strcmp(str, "keypad") == 0) {
46 		*input_device = LV_INDEV_TYPE_KEYPAD;
47 	} else if (strcmp(str, "button") == 0) {
48 		*input_device = LV_INDEV_TYPE_BUTTON;
49 	} else if (strcmp(str, "encoder") == 0) {
50 		*input_device = LV_INDEV_TYPE_ENCODER;
51 	} else {
52 		return -EINVAL;
53 	}
54 	return 0;
55 }
56 
dump_monkey_info(const struct shell * sh)57 static void dump_monkey_info(const struct shell *sh)
58 {
59 	shell_print(sh, "id   device    active");
60 	for (size_t i = 0; i < CONFIG_LV_Z_MAX_MONKEY_COUNT; i++) {
61 		if (lvgl_monkeys[i] != NULL) {
62 			shell_print(sh, "%-4u %-9s %-3s", i,
63 				    lvgl_monkey_indev_as_string(lvgl_monkeys[i]),
64 				    lv_monkey_get_enable(lvgl_monkeys[i]) ? "yes" : "no");
65 		}
66 	}
67 }
68 
cmd_lvgl_monkey(const struct shell * sh,size_t argc,char * argv[])69 static int cmd_lvgl_monkey(const struct shell *sh, size_t argc, char *argv[])
70 {
71 	ARG_UNUSED(argc);
72 	ARG_UNUSED(argv);
73 
74 	dump_monkey_info(sh);
75 	shell_print(sh, "");
76 	shell_help(sh);
77 
78 	return SHELL_CMD_HELP_PRINTED;
79 }
80 
cmd_lvgl_monkey_create(const struct shell * sh,size_t argc,char * argv[])81 static int cmd_lvgl_monkey_create(const struct shell *sh, size_t argc, char *argv[])
82 {
83 	bool created_monkey = false;
84 	lv_monkey_config_t default_config;
85 
86 	lv_monkey_config_init(&default_config);
87 
88 	if (argc == 2) {
89 		if (lvgl_monkey_indev_from_string(argv[1], &default_config.type) < 0) {
90 			shell_error(sh, "Invalid monkey input device %s", argv[1]);
91 			shell_help(sh);
92 			return SHELL_CMD_HELP_PRINTED;
93 		}
94 	}
95 
96 	for (size_t i = 0; i < CONFIG_LV_Z_MAX_MONKEY_COUNT; i++) {
97 		if (lvgl_monkeys[i] == NULL) {
98 			lvgl_monkeys[i] = lv_monkey_create(&default_config);
99 			lv_monkey_set_enable(lvgl_monkeys[i], true);
100 			created_monkey = true;
101 			break;
102 		}
103 	}
104 
105 	if (!created_monkey) {
106 		shell_error(sh, "Error creating monkey instance");
107 		return -ENOSPC;
108 	}
109 
110 	dump_monkey_info(sh);
111 
112 	return 0;
113 }
114 
cmd_lvgl_monkey_set(const struct shell * sh,size_t argc,char * argv[])115 static int cmd_lvgl_monkey_set(const struct shell *sh, size_t argc, char *argv[])
116 {
117 	int index;
118 
119 	index = atoi(argv[1]);
120 	if (index < 0 || index >= CONFIG_LV_Z_MAX_MONKEY_COUNT || lvgl_monkeys[index] == NULL) {
121 		shell_error(sh, "Invalid monkey index");
122 		return -ENOEXEC;
123 	}
124 
125 	if (strcmp(argv[2], "active") == 0) {
126 		lv_monkey_set_enable(lvgl_monkeys[index], true);
127 	} else if (strcmp(argv[2], "inactive") == 0) {
128 		lv_monkey_set_enable(lvgl_monkeys[index], false);
129 	} else {
130 		shell_error(sh, "Invalid monkey state %s", argv[2]);
131 		shell_help(sh);
132 		return SHELL_CMD_HELP_PRINTED;
133 	}
134 
135 	dump_monkey_info(sh);
136 
137 	return 0;
138 }
139 #endif /* CONFIG_LV_USE_MONKEY */
140 
cmd_lvgl_stats(const struct shell * sh,size_t argc,char * argv[])141 static int cmd_lvgl_stats(const struct shell *sh, size_t argc, char *argv[])
142 {
143 	ARG_UNUSED(argc);
144 	ARG_UNUSED(argv);
145 
146 	shell_help(sh);
147 	return SHELL_CMD_HELP_PRINTED;
148 }
149 
cmd_lvgl_stats_memory(const struct shell * sh,size_t argc,char * argv[])150 static int cmd_lvgl_stats_memory(const struct shell *sh, size_t argc, char *argv[])
151 {
152 #ifdef CONFIG_LV_Z_MEM_POOL_SYS_HEAP
153 	bool dump_chunks = false;
154 
155 	if (argc == 2) {
156 		if (strcmp(argv[1], "-c") == 0) {
157 			dump_chunks = true;
158 		} else {
159 			shell_error(sh, "unsupported option %s", argv[1]);
160 			shell_help(sh);
161 			return SHELL_CMD_HELP_PRINTED;
162 		}
163 	}
164 
165 	lvgl_print_heap_info(dump_chunks);
166 	return 0;
167 #else
168 	ARG_UNUSED(argc);
169 	ARG_UNUSED(argv);
170 	shell_error(sh, "Set CONFIG_LV_Z_MEM_POOL_SYS_HEAP to enable memory statistics support.");
171 	return -ENOTSUP;
172 #endif
173 }
174 
175 SHELL_STATIC_SUBCMD_SET_CREATE(lvgl_cmd_stats,
176 			       SHELL_CMD_ARG(memory, NULL,
177 					     "Show LVGL memory statistics\n"
178 					     "Usage: lvgl stats memory [-c]\n"
179 					     "-c  dump chunk information",
180 					     cmd_lvgl_stats_memory, 1, 1),
181 			       SHELL_SUBCMD_SET_END);
182 
183 #ifdef CONFIG_LV_USE_MONKEY
184 SHELL_STATIC_SUBCMD_SET_CREATE(
185 	lvgl_cmd_monkey,
186 	SHELL_CMD_ARG(create, NULL,
187 		      "Create a new monkey instance (default: pointer)\n"
188 		      "Usage: lvgl monkey create [pointer|keypad|button|encoder]",
189 		      cmd_lvgl_monkey_create, 1, 1),
190 	SHELL_CMD_ARG(set, NULL,
191 		      "Activate/deactive a monkey instance\n"
192 		      "Usage: lvgl monkey set <index> <active|inactive>\n",
193 		      cmd_lvgl_monkey_set, 3, 0),
194 	SHELL_SUBCMD_SET_END);
195 #endif /* CONFIG_LV_USE_MONKEY */
196 
197 SHELL_STATIC_SUBCMD_SET_CREATE(
198 	lvgl_cmds, SHELL_CMD(stats, &lvgl_cmd_stats, "Show LVGL statistics", cmd_lvgl_stats),
199 #ifdef CONFIG_LV_USE_MONKEY
200 	SHELL_CMD(monkey, &lvgl_cmd_monkey, "LVGL monkey testing", cmd_lvgl_monkey),
201 #endif /* CONFIG_LV_USE_MONKEY */
202 	SHELL_SUBCMD_SET_END);
203 
204 SHELL_CMD_REGISTER(lvgl, &lvgl_cmds, "LVGL shell commands", NULL);
205