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