apps/system: Move input/monkey to apps/graphics/input

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2025-03-19 10:47:19 +08:00 committed by Xiang Xiao
parent 7a2d5bbc64
commit 7bfd5e5790
28 changed files with 148 additions and 289 deletions

View file

@ -23,5 +23,38 @@
if(CONFIG_GRAPHICS_INPUT_GENERATOR)
nuttx_add_library(input_generator)
file(GLOB CSRCS generator/*.c)
list(REMOVE_ITEM CSRCS ${CMAKE_CURRENT_SOURCE_DIR}/generator/input.c)
target_sources(input_generator PRIVATE ${CSRCS})
endif()
if(CONFIG_GRAPHICS_INPUT_MONKEY)
file(GLOB MONKEY_SRCS monkey/*.c)
list(REMOVE_ITEM MONKEY_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/monkey/monkey_main.c)
set(SRCS monkey/monkey_main.c ${MONKEY_SRCS})
nuttx_add_application(
NAME
monkey
PRIORITY
${CONFIG_GRAPHICS_INPUT_MONKEY_PRIORITY}
STACKSIZE
${CONFIG_GRAPHICS_INPUT_MONKEY_STACKSIZE}
MODULE
${CONFIG_GRAPHICS_INPUT_MONKEY}
SRCS
${SRCS})
endif()
if(CONFIG_GRAPHICS_INPUT_TOOL)
nuttx_add_application(
MODULE
${CONFIG_GRAPHICS_INPUT_TOOL}
NAME
input
STACKSIZE
${CONFIG_GRAPHICS_INPUT_TOOL_STACKSIZE}
PRIORITY
${CONFIG_GRAPHICS_INPUT_TOOL_PRIORITY}
SRCS
generator/input.c)
endif()

View file

@ -9,3 +9,51 @@ config GRAPHICS_INPUT_GENERATOR
---help---
This is a simple input generator library that can be used to
generate input events for testing graphics applications.
menuconfig GRAPHICS_INPUT_MONKEY
tristate "Monkey test"
select UINPUT_TOUCH
select UINPUT_BUTTONS
select LIBC_PRINT_EXTENSION
default n
if GRAPHICS_INPUT_MONKEY
config GRAPHICS_INPUT_MONKEY_PRIORITY
int "Task priority"
default 110
config GRAPHICS_INPUT_MONKEY_STACKSIZE
int "Stack size"
default 4096
config GRAPHICS_INPUT_MONKEY_REC_DIR_PATH
string "Recorder directory path"
default "/data/monkey"
endif
menuconfig GRAPHICS_INPUT_TOOL
tristate "Enable input tool"
default n
select UINPUT_TOUCH
select UINPUT_BUTTONS
select UINPUT_KEYBOARD
---help---
Enable support for a command line input tool.
if GRAPHICS_INPUT_TOOL
config GRAPHICS_INPUT_TOOL_STACKSIZE
int "input stack size"
default DEFAULT_TASK_STACKSIZE
---help---
The size of stack allocated for the input task.
config GRAPHICS_INPUT_TOOL_PRIORITY
int "input priority"
default 100
---help---
The priority of the input task.
endif # GRAPHICS_INPUT_TOOL

View file

@ -23,7 +23,31 @@
include $(APPDIR)/Make.defs
ifneq ($(CONFIG_GRAPHICS_INPUT_GENERATOR),)
CSRCS = $(wildcard generator/*.c)
CSRCS = $(filter-out generator/input.c, $(wildcard generator/*.c))
endif
# Monkey test
ifneq ($(CONFIG_GRAPHICS_INPUT_MONKEY),)
PROGNAME += monkey
PRIORITY += $(CONFIG_GRAPHICS_INPUT_MONKEY_PRIORITY)
STACKSIZE += $(CONFIG_GRAPHICS_INPUT_MONKEY_STACKSIZE)
MODULE += $(CONFIG_GRAPHICS_INPUT_MONKEY)
MAINSRC += monkey/monkey_main.c
CSRCS += $(filter-out monkey/monkey_main.c, $(wildcard monkey/*.c))
endif
# Input tool
ifneq ($(CONFIG_GRAPHICS_INPUT_TOOL),)
PROGNAME += input
PRIORITY += $(CONFIG_GRAPHICS_INPUT_TOOL_PRIORITY)
STACKSIZE += $(CONFIG_GRAPHICS_INPUT_TOOL_STACKSIZE)
MODULE += $(CONFIG_GRAPHICS_INPUT_TOOL)
MAINSRC += generator/input.c
endif
include $(APPDIR)/Application.mk

View file

@ -0,0 +1,379 @@
/****************************************************************************
* apps/graphics/input/generator/input.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <unistd.h>
#include <nuttx/input/buttons.h>
#include <nuttx/input/keyboard.h>
#include <nuttx/input/touchscreen.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DEFATLT_INTERVAL 30
#define DEFATLT_DISTANCE 10
#define DELAY_MS(ms) usleep((ms) * 1000)
#define ABS(a) ((a) > 0 ? (a) : -(a))
/****************************************************************************
* Private Types
****************************************************************************/
struct input_cmd_s
{
const char *cmd; /* Command name */
int (*func)(int argc, char **argv); /* Function corresponding to command */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int input_button(int argc, char **argv);
static int input_help(int argc, char **argv);
static int input_keydown(int argc, char **argv);
static int input_keyup(int argc, char **argv);
static int input_sleep(int argc, char **argv);
static void input_utouch_move(int fd, int x, int y, int pendown);
static int input_utouch_tap(int argc, char **argv);
static int input_utouch_swipe(int argc, char **argv);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct input_cmd_s g_input_cmd_list[] =
{
{"help", input_help },
{"sleep", input_sleep },
{"tap", input_utouch_tap },
{"swipe", input_utouch_swipe},
{"button", input_button },
{"keyup", input_keyup },
{"keydown", input_keydown },
{NULL, NULL }
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: input_utouch_move
****************************************************************************/
static void input_utouch_move(int fd, int x, int y, int pendown)
{
struct touch_sample_s sample; /* Sampled touch point data */
/* Handle the change from pen down to pen up */
if (pendown != TOUCH_DOWN)
{
sample.point[0].flags = TOUCH_UP | TOUCH_ID_VALID;
}
else
{
sample.point[0].x = x;
sample.point[0].y = y;
sample.point[0].pressure = 42;
sample.point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID |
TOUCH_POS_VALID | TOUCH_PRESSURE_VALID;
}
sample.npoints = 1;
sample.point[0].h = 1;
sample.point[0].w = 1;
write(fd, &sample, sizeof(struct touch_sample_s));
}
/****************************************************************************
* Name: input_sleep
****************************************************************************/
static int input_sleep(int argc, char **argv)
{
if (argc != 2)
{
return -EINVAL;
}
DELAY_MS(atoi(argv[1]));
return 0;
}
/****************************************************************************
* Name: input_utouch_tap
****************************************************************************/
static int input_utouch_tap(int argc, char **argv)
{
int fd;
int x;
int y;
int interval = DEFATLT_INTERVAL;
if (argc < 3 || argc > 4)
{
return -EINVAL;
}
if (argc == 4)
{
interval = atoi(argv[3]);
}
x = atoi(argv[1]);
y = atoi(argv[2]);
fd = open("/dev/utouch", O_WRONLY);
if (fd < 0)
{
return -errno;
}
input_utouch_move(fd, x, y, TOUCH_DOWN);
DELAY_MS(interval);
input_utouch_move(fd, 0, 0, TOUCH_UP);
close(fd);
return 0;
}
/****************************************************************************
* Name: input_utouch_swipe
****************************************************************************/
static int input_utouch_swipe(int argc, char **argv)
{
int i;
int fd;
int x0;
int x1;
int y0;
int y1;
int count;
int duration;
int distance = DEFATLT_DISTANCE;
int interval = DEFATLT_INTERVAL;
if (argc < 5 || argc > 7)
{
return -EINVAL;
}
x0 = atoi(argv[1]);
x1 = atoi(argv[3]);
y0 = atoi(argv[2]);
y1 = atoi(argv[4]);
fd = open("/dev/utouch", O_WRONLY);
if (fd < 0)
{
return -errno;
}
/* Number of times to calculate reports */
if (argc >= 5)
{
duration = atoi(argv[5]);
}
if (argc >= 6)
{
distance = atoi(argv[6]);
distance = distance == 0 ? DEFATLT_DISTANCE : distance;
}
count = MAX(ABS(x0 - x1), ABS(y0 - y1)) / distance;
interval = duration == 0 ? DEFATLT_INTERVAL : duration / count;
for (i = 0; i <= count; i++)
{
int x = x0 + (x1 - x0) / count * i;
int y = y0 + (y1 - y0) / count * i;
input_utouch_move(fd, x, y, TOUCH_DOWN);
DELAY_MS(interval);
}
input_utouch_move(fd, x1, y1, TOUCH_UP);
close(fd);
return 0;
}
static int input_button(int argc, char **argv)
{
int fd;
btn_buttonset_t button;
if (argc != 2)
{
return -EINVAL;
}
button = strtoul(argv[1], NULL, 0);
fd = open("/dev/ubutton", O_WRONLY);
if (fd < 0)
{
return -errno;
}
write(fd, &button, sizeof(button));
close(fd);
return 0;
}
/****************************************************************************
* Name: input_keyup
****************************************************************************/
static int input_keyup(int argc, char **argv)
{
int fd;
struct keyboard_event_s key;
if (argc != 2 || argv[1] == NULL)
{
return -EINVAL;
}
fd = open("/dev/ukeyboard", O_WRONLY);
if (fd < 0)
{
return -errno;
}
key.code = strtoul(argv[1], NULL, 0);
key.type = KEYBOARD_RELEASE;
write(fd, &key, sizeof(struct keyboard_event_s));
close(fd);
return 0;
}
/****************************************************************************
* Name: input_keydown
****************************************************************************/
static int input_keydown(int argc, char **argv)
{
int fd;
struct keyboard_event_s key;
if (argc != 2 || argv[1] == NULL)
{
return -EINVAL;
}
fd = open("/dev/ukeyboard", O_WRONLY);
if (fd < 0)
{
return -errno;
}
key.code = strtoul(argv[1], NULL, 0);
key.type = KEYBOARD_PRESS;
write(fd, &key, sizeof(struct keyboard_event_s));
close(fd);
return 0;
}
/****************************************************************************
* Name: intput_help
****************************************************************************/
static int input_help(int argc, char **argv)
{
printf("Usage: input <command> [<arg>...]\n");
printf("The commands and default sources are:\n"
"\thelp\n"
"\tsleep <time(ms)>\n"
"\ttap <x> <y> [interval(ms)]\n"
"\tswipe <x1> <y1> <x2> <y2> [duration(ms)] [distance(pix)]\n"
"\tbutton <buttonvalue>\n"
"\tkeyup: <keycode>, input keyup 0x61\n"
"\tkeydown: <keycode>, input keydown 0x61\n"
"\tinterval: Time interval between two reports of sample\n"
"\tduration: Duration of sliding\n"
"\tdistance: Report the pixel distance of the sample twice\n"
"\tbuttonvalue: button value in hex format\n"
"\tkeycode: x11 key code, hexadecimal format\n"
);
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: input_main
*
* Description:
* Main entry point for the serial terminal example.
*
****************************************************************************/
int main(int argc, char **argv)
{
int i;
int ret = -EINVAL;
if (argv[1] == NULL)
{
goto errout;
}
for (i = 0; g_input_cmd_list[i].cmd != NULL; i++)
{
/* Matching the function corresponding to the command */
if (strcmp(g_input_cmd_list[i].cmd, argv[1]) == 0)
{
ret = g_input_cmd_list[i].func(argc - 1, &argv[1]);
break;
}
}
errout:
if (ret != 0)
{
input_help(argc, argv);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,201 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "monkey.h"
#include "monkey_recorder.h"
#include "monkey_assert.h"
#include "monkey_log.h"
#include "monkey_dev.h"
#include "monkey_utils.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MONKEY_DEV_PATH_TOUCH "/dev/input0"
#define MONKEY_DEV_PATH_BUTTON "/dev/buttons"
#define MONKEY_DEV_PATH_UTOUCH "/dev/utouch"
#define MONKEY_DEV_PATH_UBUTTON "/dev/ubutton"
#define MONKEY_DEV_CREATE_MATCH(monkey, type_mask, type) \
do { \
if (((type_mask) & MONKEY_DEV_TYPE_##type) == MONKEY_DEV_TYPE_##type) \
{ \
FAR struct monkey_dev_s *dev; \
dev = monkey_dev_create(MONKEY_DEV_PATH_##type, \
MONKEY_DEV_TYPE_##type); \
if (!dev) \
{ \
goto failed; \
} \
(monkey)->devs[(monkey)->dev_num] = dev; \
(monkey)->dev_num++; \
} \
} while (0)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_create
****************************************************************************/
FAR struct monkey_s *monkey_create(int dev_type_mask)
{
FAR struct monkey_s *monkey = calloc(1, sizeof(struct monkey_s));
MONKEY_ASSERT_NULL(monkey);
if (MONKEY_IS_UINPUT_TYPE(dev_type_mask))
{
MONKEY_DEV_CREATE_MATCH(monkey, dev_type_mask, UTOUCH);
MONKEY_DEV_CREATE_MATCH(monkey, dev_type_mask, UBUTTON);
}
else
{
MONKEY_DEV_CREATE_MATCH(monkey, dev_type_mask, TOUCH);
MONKEY_DEV_CREATE_MATCH(monkey, dev_type_mask, BUTTON);
}
if (monkey->dev_num == 0)
{
MONKEY_LOG_ERROR("NO enabled device detected");
goto failed;
}
MONKEY_ASSERT(monkey->dev_num <= MONKEY_DEV_MAX_NUM);
MONKEY_LOG_NOTICE("OK");
return monkey;
failed:
monkey_delete(monkey);
return NULL;
}
/****************************************************************************
* Name: monkey_delete
****************************************************************************/
void monkey_delete(FAR struct monkey_s *monkey)
{
int i;
MONKEY_ASSERT_NULL(monkey);
for (i = 0; i < monkey->dev_num; i++)
{
monkey_dev_delete(monkey->devs[i]);
}
if (monkey->recorder)
{
monkey_recorder_delete(monkey->recorder);
monkey->recorder = NULL;
}
free(monkey);
MONKEY_LOG_NOTICE("OK");
}
/****************************************************************************
* Name: monkey_config_default_init
****************************************************************************/
void monkey_config_default_init(FAR struct monkey_config_s *config)
{
MONKEY_ASSERT_NULL(config);
memset(config, 0, sizeof(struct monkey_config_s));
config->screen.hor_res = 480;
config->screen.ver_res = 480;
config->period.min = 100;
config->period.max = 500;
}
/****************************************************************************
* Name: monkey_set_config
****************************************************************************/
void monkey_set_config(FAR struct monkey_s *monkey,
FAR const struct monkey_config_s *config)
{
MONKEY_ASSERT_NULL(monkey);
MONKEY_ASSERT_NULL(config);
monkey->config = *config;
}
/****************************************************************************
* Name: monkey_set_mode
****************************************************************************/
void monkey_set_mode(FAR struct monkey_s *monkey,
enum monkey_mode_e mode)
{
MONKEY_ASSERT_NULL(monkey);
monkey->mode = mode;
}
/****************************************************************************
* Name: monkey_set_period
****************************************************************************/
void monkey_set_period(FAR struct monkey_s *monkey, uint32_t period)
{
MONKEY_ASSERT_NULL(monkey);
monkey->config.period.min = period;
monkey->config.period.max = period;
}
/****************************************************************************
* Name: monkey_set_recorder_path
****************************************************************************/
bool monkey_set_recorder_path(FAR struct monkey_s *monkey,
FAR const char *path)
{
MONKEY_ASSERT_NULL(monkey);
if (monkey->mode == MONKEY_MODE_RECORD)
{
monkey->recorder = monkey_recorder_create(path,
MONKEY_RECORDER_MODE_RECORD);
}
else if (monkey->mode == MONKEY_MODE_PLAYBACK)
{
monkey->recorder = monkey_recorder_create(path,
MONKEY_RECORDER_MODE_PLAYBACK);
}
else
{
MONKEY_LOG_WARN("mismatched mode: %d", monkey->mode);
}
return (monkey->recorder != NULL);
}

View file

@ -0,0 +1,100 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include "monkey_type.h"
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: monkey_create
****************************************************************************/
FAR struct monkey_s *monkey_create(int dev_type_mask);
/****************************************************************************
* Name: monkey_update
****************************************************************************/
int monkey_update(FAR struct monkey_s *monkey);
/****************************************************************************
* Name: monkey_delete
****************************************************************************/
void monkey_delete(FAR struct monkey_s *monkey);
/****************************************************************************
* Name: monkey_config_default_init
****************************************************************************/
void monkey_config_default_init(FAR struct monkey_config_s *config);
/****************************************************************************
* Name: monkey_set_config
****************************************************************************/
void monkey_set_config(FAR struct monkey_s *monkey,
FAR const struct monkey_config_s *config);
/****************************************************************************
* Name: monkey_set_mode
****************************************************************************/
void monkey_set_mode(FAR struct monkey_s *monkey, enum monkey_mode_e mode);
/****************************************************************************
* Name: monkey_set_period
****************************************************************************/
void monkey_set_period(FAR struct monkey_s *monkey, uint32_t period);
/****************************************************************************
* Name: monkey_set_recorder_path
****************************************************************************/
bool monkey_set_recorder_path(FAR struct monkey_s *monkey,
FAR const char *path);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_H */

View file

@ -0,0 +1,39 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_assert.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_ASSERT_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_ASSERT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <assert.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MONKEY_ASSERT(expr) DEBUGASSERT(expr)
#define MONKEY_ASSERT_NULL(ptr) MONKEY_ASSERT(ptr != NULL)
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_ASSERT_H */

View file

@ -0,0 +1,327 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_dev.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <nuttx/input/buttons.h>
#include <nuttx/input/touchscreen.h>
#include <poll.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "monkey_assert.h"
#include "monkey_log.h"
#include "monkey_dev.h"
#include "monkey_utils.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: utouch_write
****************************************************************************/
static void utouch_write(int fd, int x, int y, int touch_down)
{
struct touch_sample_s sample;
if (touch_down)
{
sample.point[0].x = x;
sample.point[0].y = y;
sample.point[0].pressure = 42;
sample.point[0].flags = TOUCH_DOWN | TOUCH_ID_VALID |
TOUCH_POS_VALID | TOUCH_PRESSURE_VALID;
}
else
{
sample.point[0].flags = TOUCH_UP | TOUCH_ID_VALID;
}
sample.npoints = 1;
sample.point[0].h = 1;
sample.point[0].w = 1;
write(fd, &sample, sizeof(struct touch_sample_s));
MONKEY_LOG_INFO("%s at x = %d, y = %d",
touch_down ? "PRESS " : "RELEASE", x, y);
}
/****************************************************************************
* Name: ubutton_write
****************************************************************************/
static void ubutton_write(int fd, uint32_t btn_bits)
{
btn_buttonset_t buttonset = btn_bits;
write(fd, &buttonset, sizeof(buttonset));
MONKEY_LOG_INFO("btn = 0x%08X", btn_bits);
}
/****************************************************************************
* Name: touch_read
****************************************************************************/
static bool touch_read(int fd, FAR int *x, FAR int *y, FAR int *touch_down)
{
bool retval = false;
struct touch_sample_s sample;
int nbytes = read(fd, &sample, sizeof(sample));
if (nbytes == sizeof(sample))
{
retval = true;
uint8_t touch_flags = sample.point[0].flags;
if (touch_flags & TOUCH_DOWN || touch_flags & TOUCH_MOVE)
{
*x = sample.point[0].x;
*y = sample.point[0].y;
*touch_down = true;
}
else if (touch_flags & TOUCH_UP)
{
*x = 0;
*y = 0;
*touch_down = false;
}
}
return retval;
}
/****************************************************************************
* Name: button_read
****************************************************************************/
static bool button_read(int fd, FAR uint32_t *value)
{
btn_buttonset_t buttonset;
int nbytes = read(fd, &buttonset, sizeof(buttonset));
if (nbytes != sizeof(buttonset))
{
return false;
}
*value = buttonset;
return true;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_dev_create
****************************************************************************/
FAR struct monkey_dev_s *monkey_dev_create(FAR const char *dev_path,
enum monkey_dev_type_e type)
{
FAR struct monkey_dev_s *dev;
int oflag;
int fd;
MONKEY_ASSERT_NULL(dev_path);
dev = calloc(1, sizeof(struct monkey_dev_s));
MONKEY_ASSERT_NULL(dev);
if (MONKEY_IS_UINPUT_TYPE(type))
{
oflag = O_RDWR | O_NONBLOCK;
}
else
{
oflag = O_RDONLY | O_NONBLOCK;
}
fd = open(dev_path, oflag);
if (fd < 0)
{
MONKEY_LOG_ERROR("open %s failed: %d", dev_path, errno);
goto failed;
}
dev->type = type;
dev->fd = fd;
MONKEY_LOG_NOTICE("open %s success, fd = %d, type: %s",
dev_path, fd, monkey_dev_type2name(type));
return dev;
failed:
if (fd > 0)
{
close(fd);
}
if (dev)
{
free(dev);
}
return NULL;
}
/****************************************************************************
* Name: monkey_dev_delete
****************************************************************************/
void monkey_dev_delete(FAR struct monkey_dev_s *dev)
{
MONKEY_ASSERT_NULL(dev);
if (dev->fd > 0)
{
/* Reset input state */
struct monkey_dev_state_s state;
memset(&state, 0, sizeof(state));
state.type = dev->type;
monkey_dev_set_state(dev, &state);
MONKEY_LOG_NOTICE("close fd: %d", dev->fd);
close(dev->fd);
}
free(dev);
}
/****************************************************************************
* Name: monkey_dev_set_state
****************************************************************************/
void monkey_dev_set_state(FAR struct monkey_dev_s *dev,
FAR const struct monkey_dev_state_s *state)
{
MONKEY_ASSERT_NULL(dev);
switch (MONKEY_GET_DEV_TYPE(dev->type))
{
case MONKEY_DEV_TYPE_TOUCH:
utouch_write(dev->fd,
state->data.touch.x,
state->data.touch.y,
state->data.touch.is_pressed);
break;
case MONKEY_DEV_TYPE_BUTTON:
ubutton_write(dev->fd, state->data.button.value);
break;
default:
break;
}
}
/****************************************************************************
* Name: monkey_dev_get_state
****************************************************************************/
bool monkey_dev_get_state(FAR struct monkey_dev_s *dev,
FAR struct monkey_dev_state_s *state)
{
bool retval;
MONKEY_ASSERT_NULL(dev);
retval = false;
state->type = dev->type;
switch (dev->type)
{
case MONKEY_DEV_TYPE_TOUCH:
retval = touch_read(dev->fd,
&state->data.touch.x,
&state->data.touch.y,
&state->data.touch.is_pressed);
break;
case MONKEY_DEV_TYPE_BUTTON:
retval = button_read(dev->fd, &state->data.button.value);
break;
default:
break;
}
return retval;
}
/****************************************************************************
* Name: monkey_dev_get_state
****************************************************************************/
enum monkey_dev_type_e monkey_dev_get_type(
FAR struct monkey_dev_s *dev)
{
MONKEY_ASSERT_NULL(dev);
return dev->type;
}
/****************************************************************************
* Name: monkey_dev_get_available
****************************************************************************/
int monkey_dev_get_available(FAR struct monkey_dev_s *devs[], int dev_num)
{
int i;
int available = 0;
struct pollfd fds[MONKEY_DEV_MAX_NUM];
memset(fds, 0, sizeof(fds));
for (i = 0; i < dev_num; i++)
{
devs[i]->is_available = false;
fds[i].fd = devs[i]->fd;
fds[i].events = POLLIN | POLLPRI;
}
if (poll(fds, dev_num, -1) < 0)
{
MONKEY_LOG_WARN("stop: %d", errno);
return -1;
}
for (i = 0; i < dev_num; i++)
{
if (fds[i].revents & (POLLIN | POLLPRI))
{
devs[i]->is_available = true;
available++;
}
}
return available;
}

View file

@ -0,0 +1,99 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_dev.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_DEV_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_DEV_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "monkey_type.h"
/****************************************************************************
* Public Types
****************************************************************************/
struct monkey_dev_s
{
int fd;
enum monkey_dev_type_e type;
bool is_available;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: monkey_dev_create
****************************************************************************/
FAR struct monkey_dev_s *monkey_dev_create(FAR const char *dev_path,
enum monkey_dev_type_e type);
/****************************************************************************
* Name: monkey_dev_delete
****************************************************************************/
void monkey_dev_delete(FAR struct monkey_dev_s *dev);
/****************************************************************************
* Name: monkey_dev_set_state
****************************************************************************/
void monkey_dev_set_state(FAR struct monkey_dev_s *dev,
FAR const struct monkey_dev_state_s *state);
/****************************************************************************
* Name: monkey_dev_get_state
****************************************************************************/
bool monkey_dev_get_state(FAR struct monkey_dev_s *dev,
FAR struct monkey_dev_state_s *state);
/****************************************************************************
* Name: monkey_dev_get_type
****************************************************************************/
enum monkey_dev_type_e monkey_dev_get_type(FAR struct monkey_dev_s *dev);
/****************************************************************************
* Name: monkey_dev_get_available
****************************************************************************/
int monkey_dev_get_available(FAR struct monkey_dev_s *devs[], int dev_num);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_DEV_H */

View file

@ -0,0 +1,203 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_event.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <string.h>
#include <unistd.h>
#include "monkey_dev.h"
#include "monkey_event.h"
#include "monkey_log.h"
#include "monkey_utils.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_exec_darg
****************************************************************************/
static bool monkey_exec_darg(FAR struct monkey_dev_s *dev,
FAR struct monkey_dev_state_s *state,
FAR const struct monkey_event_param_s *param)
{
int t = 0;
uint32_t start;
state->data.touch.is_pressed = true;
start = monkey_tick_get();
while (t < param->duration)
{
t = monkey_tick_elaps(monkey_tick_get(), start);
state->data.touch.x = monkey_map(t, 0, param->duration,
param->x1, param->x2);
state->data.touch.y = monkey_map(t, 0, param->duration,
param->y1, param->y2);
monkey_dev_set_state(dev, state);
if (usleep(1000) < 0)
{
return false;
}
}
return true;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_event_gen
****************************************************************************/
void monkey_event_gen(FAR struct monkey_s *monkey,
FAR struct monkey_event_param_s *param)
{
int weight = 0;
int total = 0;
int i;
int rnd;
int duration_min;
int duration_max;
int x_offset;
int y_offset;
memset(param, 0, sizeof(struct monkey_event_param_s));
/* Calculate total weight */
for (i = 0; i < MONKEY_EVENT_LAST; i++)
{
total += monkey->config.event[i].weight;
}
rnd = monkey_random(0, total);
/* Select random events based on weight */
for (i = 0; i < MONKEY_EVENT_LAST; i++)
{
weight += monkey->config.event[i].weight;
if (rnd < weight)
{
param->event = i;
break;
}
}
duration_min = monkey->config.event[param->event].duration_min;
duration_max = monkey->config.event[param->event].duration_max;
x_offset = monkey->config.screen.x_offset;
y_offset = monkey->config.screen.y_offset;
param->duration = monkey_random(duration_min, duration_max);
param->x1 = monkey_random(x_offset,
x_offset + monkey->config.screen.hor_res - 1);
param->y1 = monkey_random(y_offset,
y_offset + monkey->config.screen.ver_res - 1);
param->x2 = monkey_random(x_offset,
x_offset + monkey->config.screen.hor_res - 1);
param->y2 = monkey_random(y_offset,
y_offset + monkey->config.screen.ver_res - 1);
MONKEY_LOG_INFO("event=%d(%s) duration=%d x1=%d y1=%d x2=%d y2=%d",
param->event,
monkey_event_type2name(param->event),
param->duration,
param->x1, param->y1,
param->x2, param->y2);
}
/****************************************************************************
* Name: monkey_event_exec
****************************************************************************/
bool monkey_event_exec(FAR struct monkey_s *monkey,
FAR struct monkey_dev_s *dev,
FAR const struct monkey_event_param_s *param)
{
bool retval = false;
struct monkey_dev_state_s state;
memset(&state, 0, sizeof(struct monkey_dev_state_s));
state.type = monkey_dev_get_type(dev);
MONKEY_LOG_INFO("dev=0x%x event=%d(%s) duration=%d"
" x1=%d y1=%d x2=%d y2=%d",
state.type,
param->event,
monkey_event_type2name(param->event),
param->duration,
param->x1, param->y1,
param->x2, param->y2);
if (state.type & MONKEY_DEV_TYPE_TOUCH)
{
state.data.touch.x = param->x1;
state.data.touch.y = param->y1;
state.data.touch.is_pressed = true;
monkey_dev_set_state(dev, &state);
if (param->event == MONKEY_EVENT_DRAG)
{
retval = monkey_exec_darg(dev, &state, param);
}
else
{
retval = usleep(param->duration * 1000) == 0;
}
if (!retval)
{
MONKEY_LOG_NOTICE("detect monkey killed");
}
state.data.touch.is_pressed = false;
monkey_dev_set_state(dev, &state);
}
else if (state.type & MONKEY_DEV_TYPE_BUTTON)
{
/* press button */
state.data.button.value = 1 << monkey->config.btn_bit;
monkey_dev_set_state(dev, &state);
retval = usleep(param->duration * 1000) == 0;
/* release button */
state.data.button.value = 0;
monkey_dev_set_state(dev, &state);
}
else
{
MONKEY_LOG_WARN("unsupport device type: %d", state.type);
}
return retval;
}

View file

@ -0,0 +1,79 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_event.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_EVENT_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_EVENT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include "monkey_type.h"
/****************************************************************************
* Public Types
****************************************************************************/
struct monkey_event_param_s
{
enum monkey_event_e event;
int duration;
int x1;
int y1;
int x2;
int y2;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: monkey_event_gen
****************************************************************************/
void monkey_event_gen(FAR struct monkey_s *monkey,
FAR struct monkey_event_param_s *param);
/****************************************************************************
* Name: monkey_event_exec
****************************************************************************/
bool monkey_event_exec(FAR struct monkey_s *monkey,
FAR struct monkey_dev_s *dev,
FAR const struct monkey_event_param_s *param);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_EVENT_H */

View file

@ -0,0 +1,97 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_log.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdarg.h>
#include <syslog.h>
#include <nuttx/streams.h>
#include "monkey_log.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static enum monkey_log_level_type_e g_log_level = MONKEY_LOG_LEVEL_NOTICE;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_log_printf
****************************************************************************/
void monkey_log_printf(enum monkey_log_level_type_e level,
FAR const char *func,
FAR const char *fmt,
...)
{
struct va_format vaf;
va_list ap;
static const int priority[MONKEY_LOG_LEVEL_LAST] =
{
LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR
};
if (level < g_log_level)
{
return;
}
va_start(ap, fmt);
vaf.fmt = fmt;
vaf.va = &ap;
syslog(priority[level], "[monkey] %s: %pV\n", func, &vaf);
va_end(ap);
}
/****************************************************************************
* Name: monkey_log_set_level
****************************************************************************/
void monkey_log_set_level(enum monkey_log_level_type_e level)
{
if (level >= MONKEY_LOG_LEVEL_LAST)
{
MONKEY_LOG_WARN("error level: %d", level);
return;
}
g_log_level = level;
}
/****************************************************************************
* Name: monkey_log_get_level
****************************************************************************/
enum monkey_log_level_type_e monkey_log_get_level(void)
{
return g_log_level;
}

View file

@ -0,0 +1,108 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_log.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_LOG_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_LOG_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MONKEY_LOG_INFO(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_INFO, \
__func__, \
format, \
##__VA_ARGS__)
#define MONKEY_LOG_NOTICE(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_NOTICE, \
__func__, \
format, \
##__VA_ARGS__)
#define MONKEY_LOG_WARN(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_WARN, \
__func__, \
format, \
##__VA_ARGS__)
#define MONKEY_LOG_ERROR(format, ...) \
monkey_log_printf(MONKEY_LOG_LEVEL_ERROR, \
__func__, \
format, \
##__VA_ARGS__)
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Types
****************************************************************************/
enum monkey_log_level_type_e
{
MONKEY_LOG_LEVEL_INFO,
MONKEY_LOG_LEVEL_NOTICE,
MONKEY_LOG_LEVEL_WARN,
MONKEY_LOG_LEVEL_ERROR,
MONKEY_LOG_LEVEL_LAST
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: monkey_log_printf
****************************************************************************/
void monkey_log_printf(enum monkey_log_level_type_e level,
FAR const char *func,
FAR const char *fmt,
...);
/****************************************************************************
* Name: monkey_log_set_level
****************************************************************************/
void monkey_log_set_level(enum monkey_log_level_type_e level);
/****************************************************************************
* Name: monkey_log_get_level
****************************************************************************/
enum monkey_log_level_type_e monkey_log_get_level(void);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_LOG_H */

View file

@ -0,0 +1,631 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_main.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/video/fb.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/ioctl.h>
#include "monkey.h"
#include "monkey_utils.h"
#include "monkey_log.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MONKEY_PREFIX "monkey"
#define CONSTRAIN(x, low, high) \
((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
#define OPTARG_TO_VALUE(value, type, base) \
do \
{ \
FAR char *ptr; \
(value) = (type)strtoul(optarg, &ptr, (base)); \
if (*ptr != '\0') \
{ \
MONKEY_LOG_ERROR("Parameter error: -%c %s", ch, optarg); \
show_usage(argv[0], EXIT_FAILURE); \
} \
} while (0)
#define OPTARG_TO_RANGE(value_1, value_2, delimiter) \
do \
{ \
int converted; \
int v1; \
int v2; \
converted = sscanf(optarg, "%d" delimiter "%d", &v1, &v2); \
if (converted == 2 && v1 >= 0 && v2 >= 0) \
{ \
value_1 = v1; \
value_2 = v2; \
} \
else \
{ \
MONKEY_LOG_ERROR("Error range: %s", optarg); \
show_usage(argv[0], EXIT_FAILURE); \
} \
} while (0)
/* Default parameters */
#if defined(CONFIG_VIDEO_FB)
# define MONKEY_SCREEN_DEV "/dev/fb0"
# define MONKEY_SCREEN_GETVIDEOINFO FBIOGET_VIDEOINFO
#elif defined(CONFIG_LCD)
# define MONKEY_SCREEN_DEV "/dev/lcd0"
# define MONKEY_SCREEN_GETVIDEOINFO LCDDEVIO_GETVIDEOINFO
#endif
#define MONKEY_RUNNING_MINUTES_MAX (UINT32_MAX / 60 / 1000)
#define MONKEY_SCREEN_HOR_RES_DEFAULT 480
#define MONKEY_SCREEN_VER_RES_DEFAULT 480
#define MONKEY_PERIOD_MIN_DEFAULT 100
#define MONKEY_PERIOD_MAX_DEFAULT 500
#define MONKEY_BUTTON_BIT_DEFAULT 0
#define MONKEY_EVENT_CLICK_WEIGHT_DEFAULT 70
#define MONKEY_EVENT_LONG_PRESS_WEIGHT_DEFAULT 10
#define MONKEY_EVENT_DRAG_WEIGHT_DEFAULT 20
#define MONKEY_EVENT_CLICK_DURATION_MIN_DEFAULT 50
#define MONKEY_EVENT_CLICK_DURATION_MAX_DEFAULT 200
#define MONKEY_EVENT_LONG_PRESS_DURATION_MIN_DEFAULT 400
#define MONKEY_EVENT_LONG_PRESS_DURATION_MAX_DEFAULT 600
#define MONKEY_EVENT_DRAG_DURATION_MIN_DEFAULT 100
#define MONKEY_EVENT_DRAG_DURATION_MAX_DEFAULT 400
#define MONKEY_EVENT_PARAM_INIT(name) \
do \
{ \
param->event[MONKEY_EVENT_##name].weight = \
MONKEY_EVENT_##name##_WEIGHT_DEFAULT; \
param->event[MONKEY_EVENT_##name].duration_min = \
MONKEY_EVENT_##name##_DURATION_MIN_DEFAULT; \
param->event[MONKEY_EVENT_##name].duration_max = \
MONKEY_EVENT_##name##_DURATION_MAX_DEFAULT; \
} while (0)
/****************************************************************************
* Private Types
****************************************************************************/
struct monkey_param_s
{
int dev_type_mask;
FAR const char *file_path;
int x_offset;
int y_offset;
int hor_res;
int ver_res;
int period_min;
int period_max;
int btn_bit;
int log_level;
struct monkey_event_config_s event[MONKEY_EVENT_LAST];
uint32_t running_minutes;
};
enum monkey_wait_res_e
{
MONKEY_WAIT_RES_AGAIN,
MONKEY_WAIT_RES_PAUSE,
MONKEY_WAIT_RES_STOP,
MONKEY_WAIT_RES_ERROR,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: show_usage
****************************************************************************/
static void show_usage(FAR const char *progname, int exitcode)
{
printf("\nUsage: %s"
" -t <hex-value>"
" -f <string>"
" -p <string>"
" -s <string>"
" -b <decimal-value>"
" -l <decimal-value>\n"
" --weight-click <decimal-value>"
" --weight-longpress <decimal-value>"
" --weight-drag <decimal-value>\n"
" --duration-click <string>"
" --duration-longpress <string>"
" --duration-drag <string>\n"
" --screen-offset <string>\n"
" --running-minutes <decimal-value>\n",
progname);
printf("\nWhere:\n");
printf(" -t <hex-value> Device type mask: uinput = 0x%02X;"
" touch = 0x%02X; button = 0x%02X.\n",
MONKEY_UINPUT_TYPE_MASK,
MONKEY_DEV_TYPE_TOUCH,
MONKEY_DEV_TYPE_BUTTON);
printf(" -f <string> Recorder playback file path.\n");
printf(" -p <string> Period(ms) range: "
"<decimal-value min>-<decimal-value max>\n");
printf(" -s <string> Screen resolution: "
"<decimal-value hor_res>x<decimal-value ver_res>\n");
printf(" -b <decimal-value> Button bit: 0 ~ 31\n");
printf(" -l <decimal-value> Log level: 0 ~ 3\n");
printf(" --weight-click <decimal-value> Click event weight.\n");
printf(" --weight-longpress <decimal-value> Long press event weight.\n");
printf(" --weight-drag <decimal-value> Drag event weight.\n");
printf(" --duration-click <string> Click duration(ms) range: "
"<decimal-value min>-<decimal-value max>.\n");
printf(" --duration-longpress <string> Long press duration(ms) range: "
"<decimal-value min>-<decimal-value max>.\n");
printf(" --duration-drag <string> Drag duration(ms) range: "
"<decimal-value min>-<decimal-value max>.\n");
printf(" --screen-offset <string> Screen offset: "
"<decimal-value x_offset>,<decimal-value y_offset>\n");
printf(" --running-minutes <decimal-value> Running minutes.\n");
exit(exitcode);
}
/****************************************************************************
* Name: monkey_get_screen_resolution
****************************************************************************/
static int monkey_get_screen_resolution(FAR int *hor_res, FAR int *ver_res)
{
#ifdef MONKEY_SCREEN_DEV
struct fb_videoinfo_s vinfo;
int fd;
int ret;
FAR const char *dev_path = MONKEY_SCREEN_DEV;
*hor_res = MONKEY_SCREEN_HOR_RES_DEFAULT;
*ver_res = MONKEY_SCREEN_VER_RES_DEFAULT;
fd = open(dev_path, 0);
if (fd < 0)
{
MONKEY_LOG_ERROR("screen dev %s open failed: %d", dev_path, errno);
return ERROR;
}
ret = ioctl(fd, MONKEY_SCREEN_GETVIDEOINFO,
(unsigned long)((uintptr_t)&vinfo));
if (ret < 0)
{
MONKEY_LOG_ERROR("get video info failed: %d", errno);
}
else
{
*hor_res = vinfo.xres;
*ver_res = vinfo.yres;
}
close(fd);
return ret;
#else
*hor_res = MONKEY_SCREEN_HOR_RES_DEFAULT;
*ver_res = MONKEY_SCREEN_VER_RES_DEFAULT;
return OK;
#endif /* MONKEY_SCREEN_DEV */
}
/****************************************************************************
* Name: monkey_init
****************************************************************************/
static FAR struct monkey_s *monkey_init(
FAR const struct monkey_param_s *param)
{
FAR struct monkey_s *monkey;
struct monkey_config_s config;
int i;
if (!param->dev_type_mask)
{
show_usage(MONKEY_PREFIX, EXIT_FAILURE);
}
monkey = monkey_create(param->dev_type_mask);
if (!monkey)
{
goto failed;
}
monkey_config_default_init(&config);
config.screen.x_offset = param->x_offset;
config.screen.y_offset = param->y_offset;
config.screen.hor_res = param->hor_res;
config.screen.ver_res = param->ver_res;
config.period.min = param->period_min;
config.period.max = param->period_max;
config.btn_bit = param->btn_bit;
memcpy(config.event, param->event, sizeof(config.event));
monkey_set_config(monkey, &config);
monkey_log_set_level(param->log_level);
MONKEY_LOG_NOTICE("Screen: %dx%d, offset: %d,%d",
config.screen.hor_res,
config.screen.ver_res,
config.screen.x_offset,
config.screen.y_offset);
MONKEY_LOG_NOTICE("Period: %" PRIu32 " ~ %" PRIu32 "ms",
config.period.min,
config.period.max);
MONKEY_LOG_NOTICE("Button bit: %d", config.btn_bit);
MONKEY_LOG_NOTICE("Log level: %d", monkey_log_get_level());
for (i = 0; i < MONKEY_EVENT_LAST; i++)
{
MONKEY_LOG_NOTICE("Event %d(%s): weight=%d"
" duration %d ~ %dms",
i,
monkey_event_type2name(i),
config.event[i].weight,
config.event[i].duration_min,
config.event[i].duration_max);
}
MONKEY_LOG_NOTICE("Running minutes: %" PRIu32, param->running_minutes);
if (MONKEY_IS_UINPUT_TYPE(param->dev_type_mask))
{
if (param->file_path)
{
monkey_set_mode(monkey, MONKEY_MODE_PLAYBACK);
if (!monkey_set_recorder_path(monkey, param->file_path))
{
goto failed;
}
}
else
{
monkey_set_mode(monkey, MONKEY_MODE_RANDOM);
}
}
else
{
monkey_set_mode(monkey, MONKEY_MODE_RECORD);
if (!monkey_set_recorder_path(monkey,
CONFIG_GRAPHICS_INPUT_MONKEY_REC_DIR_PATH))
{
goto failed;
}
monkey_set_period(monkey, config.period.min);
}
return monkey;
failed:
if (monkey)
{
monkey_delete(monkey);
}
return NULL;
}
/****************************************************************************
* Name: parse_long_commandline
****************************************************************************/
static void parse_long_commandline(int argc, FAR char **argv,
int ch,
FAR const struct option *longopts,
int longindex,
FAR struct monkey_param_s *param)
{
int event_index;
switch (longindex)
{
case 0:
case 1:
case 2:
event_index = longindex;
OPTARG_TO_VALUE(param->event[event_index].weight, uint8_t, 10);
break;
case 3:
case 4:
case 5:
event_index = longindex - 3;
OPTARG_TO_RANGE(param->event[event_index].duration_min,
param->event[event_index].duration_max,
"-");
break;
case 6:
OPTARG_TO_RANGE(param->x_offset,
param->y_offset,
",");
break;
case 7:
OPTARG_TO_VALUE(param->running_minutes, uint32_t, 10);
if (param->running_minutes > MONKEY_RUNNING_MINUTES_MAX)
{
MONKEY_LOG_WARN("Running minutes must be less than %d",
MONKEY_RUNNING_MINUTES_MAX);
param->running_minutes = MONKEY_RUNNING_MINUTES_MAX;
}
break;
default:
MONKEY_LOG_WARN("Unknown longindex: %d", longindex);
show_usage(argv[0], EXIT_FAILURE);
break;
}
}
/****************************************************************************
* Name: parse_commandline
****************************************************************************/
static void parse_commandline(int argc, FAR char **argv,
FAR struct monkey_param_s *param)
{
int ch;
int longindex = 0;
FAR const char *optstring = "t:f:p:s:b:l:";
const struct option longopts[] =
{
{"weight-click", required_argument, NULL, 0 },
{"weight-longpress", required_argument, NULL, 0 },
{"weight-drag", required_argument, NULL, 0 },
{"duration-click", required_argument, NULL, 0 },
{"duration-longpress", required_argument, NULL, 0 },
{"duration-drag", required_argument, NULL, 0 },
{"screen-offset", required_argument, NULL, 0 },
{"running-minutes", required_argument, NULL, 0 },
{0, 0, NULL, 0 }
};
memset(param, 0, sizeof(struct monkey_param_s));
monkey_get_screen_resolution(&param->hor_res, &param->ver_res);
param->period_min = MONKEY_PERIOD_MIN_DEFAULT;
param->period_max = MONKEY_PERIOD_MAX_DEFAULT;
param->btn_bit = MONKEY_BUTTON_BIT_DEFAULT;
param->log_level = MONKEY_LOG_LEVEL_NOTICE;
MONKEY_EVENT_PARAM_INIT(CLICK);
MONKEY_EVENT_PARAM_INIT(LONG_PRESS);
MONKEY_EVENT_PARAM_INIT(DRAG);
while ((ch = getopt_long(argc, argv,
optstring, longopts, &longindex)) != ERROR)
{
switch (ch)
{
case 0:
parse_long_commandline(argc, argv, ch,
longopts, longindex, param);
break;
case 't':
OPTARG_TO_VALUE(param->dev_type_mask, int, 16);
break;
case 'f':
param->file_path = optarg;
break;
case 'p':
OPTARG_TO_RANGE(param->period_min, param->period_max, "-");
break;
case 's':
OPTARG_TO_RANGE(param->hor_res, param->ver_res, "x");
break;
case 'b':
OPTARG_TO_VALUE(param->btn_bit, int, 10);
param->btn_bit = CONSTRAIN(param->btn_bit, 0, 31);
break;
case 'l':
OPTARG_TO_VALUE(param->log_level, int, 10);
param->log_level = CONSTRAIN(param->log_level, 0,
MONKEY_LOG_LEVEL_LAST - 1);
break;
case '?':
MONKEY_LOG_WARN("Unknown option: %c", optopt);
show_usage(argv[0], EXIT_FAILURE);
break;
}
}
}
/****************************************************************************
* Name: monkey_pause
****************************************************************************/
static int monkey_pause(void)
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGCONT);
return sigwaitinfo(&set, NULL);
}
/****************************************************************************
* Name: monkey_wait
****************************************************************************/
static enum monkey_wait_res_e monkey_wait(uint32_t ms)
{
sigset_t set;
struct timespec timeout;
int ret;
enum monkey_wait_res_e res = MONKEY_WAIT_RES_ERROR;
if (ms == 0)
{
return MONKEY_WAIT_RES_AGAIN;
}
timeout.tv_sec = ms / 1000;
timeout.tv_nsec = (ms % 1000) * 1000000;
sigemptyset(&set);
sigaddset(&set, SIGTSTP);
ret = sigtimedwait(&set, NULL, &timeout);
if (ret < 0)
{
int errcode = errno;
if (errcode == EINTR)
{
res = MONKEY_WAIT_RES_STOP;
}
else if(errcode == EAGAIN)
{
res = MONKEY_WAIT_RES_AGAIN;
}
else
{
MONKEY_LOG_ERROR("Unknow error: %d", errcode);
}
}
else if (ret == SIGTSTP)
{
res = MONKEY_WAIT_RES_PAUSE;
}
return res;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_main
*
* Description:
*
* Input Parameters:
* Standard argc and argv
*
* Returned Value:
* Zero on success; a positive, non-zero value on failure.
*
****************************************************************************/
int main(int argc, FAR char *argv[])
{
struct monkey_param_s param;
FAR struct monkey_s *monkey;
uint32_t start_tick;
parse_commandline(argc, argv, &param);
monkey = monkey_init(&param);
if (!monkey)
{
return ERROR;
}
start_tick = monkey_tick_get();
while (1)
{
enum monkey_wait_res_e res;
int sleep_ms;
if (param.running_minutes > 0)
{
uint32_t elaps = monkey_tick_elaps(monkey_tick_get(), start_tick);
if (elaps > param.running_minutes * 60 * 1000)
{
MONKEY_LOG_WARN("Running time is over: %" PRIu32
" minutes, exit...",
param.running_minutes);
break;
}
}
sleep_ms = monkey_update(monkey);
if (sleep_ms < 0)
{
break;
}
res = monkey_wait(sleep_ms);
if (res == MONKEY_WAIT_RES_AGAIN)
{
continue;
}
else if (res == MONKEY_WAIT_RES_PAUSE)
{
MONKEY_LOG_NOTICE("pause");
if (monkey_pause() < 0)
{
break;
}
MONKEY_LOG_NOTICE("continue...");
}
else
{
/* STOP or ERROR */
break;
}
}
monkey_delete(monkey);
return OK;
}

View file

@ -0,0 +1,317 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_proc.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include "monkey.h"
#include "monkey_assert.h"
#include "monkey_dev.h"
#include "monkey_event.h"
#include "monkey_log.h"
#include "monkey_recorder.h"
#include "monkey_utils.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_update_uinput_ramdom
****************************************************************************/
static bool monkey_update_uinput_ramdom(FAR struct monkey_s *monkey)
{
int i;
bool retval = false;
for (i = 0; i < monkey->dev_num; i++)
{
FAR struct monkey_dev_s *dev = monkey->devs[i];
struct monkey_event_param_s param;
monkey_event_gen(monkey, &param);
retval = monkey_event_exec(monkey, dev, &param);
if (!retval)
{
break;
}
}
return retval;
}
/****************************************************************************
* Name: monkey_search_dev
****************************************************************************/
static FAR struct monkey_dev_s *monkey_search_dev(
FAR struct monkey_s *monkey,
enum monkey_dev_type_e type)
{
int i;
for (i = 0; i < monkey->dev_num; i++)
{
FAR struct monkey_dev_s *dev = monkey->devs[i];
if (type == dev->type)
{
return dev;
}
}
return NULL;
}
/****************************************************************************
* Name: monkey_recorder_get_next
****************************************************************************/
static int monkey_recorder_get_next(FAR struct monkey_s *monkey,
FAR uint32_t *cur_time_stamp_p,
FAR struct monkey_dev_state_s *cur_state_p,
FAR uint32_t *next_time_stamp_p,
FAR struct monkey_dev_state_s *next_state_p)
{
enum monkey_recorder_res_e res;
if (monkey->playback_ctx.time_stamp == 0)
{
res = monkey_recorder_read(monkey->recorder,
cur_state_p,
cur_time_stamp_p);
if (res != MONKEY_RECORDER_RES_OK)
{
MONKEY_LOG_ERROR("read first line failed: %d", res);
return 0;
}
}
else
{
*cur_time_stamp_p = monkey->playback_ctx.time_stamp;
*cur_state_p = monkey->playback_ctx.state;
}
res = monkey_recorder_read(monkey->recorder,
next_state_p,
next_time_stamp_p);
if (res != MONKEY_RECORDER_RES_OK)
{
if (res == MONKEY_RECORDER_RES_END_OF_FILE)
{
MONKEY_LOG_WARN("end of file");
return 1;
}
MONKEY_LOG_ERROR("read error: %d", res);
return 0;
}
monkey->playback_ctx.time_stamp = *next_time_stamp_p;
monkey->playback_ctx.state = *next_state_p;
return 2;
}
/****************************************************************************
* Name: monkey_update_uinput_playback
****************************************************************************/
static bool monkey_update_uinput_playback(FAR struct monkey_s *monkey)
{
FAR uint32_t cur_time_stamp;
struct monkey_dev_state_s cur_state;
FAR uint32_t next_time_stamp;
struct monkey_dev_state_s next_state;
uint32_t tick_elaps;
FAR struct monkey_dev_s *dev;
int num_of_get;
MONKEY_ASSERT_NULL(monkey->recorder);
num_of_get = monkey_recorder_get_next(monkey,
&cur_time_stamp,
&cur_state,
&next_time_stamp,
&next_state);
switch (num_of_get)
{
case 1:
next_time_stamp = cur_time_stamp;
memset(&monkey->playback_ctx, 0, sizeof(monkey->playback_ctx));
monkey_recorder_reset(monkey->recorder);
case 2:
dev = monkey_search_dev(monkey,
MONKEY_UINPUT_TYPE_MASK | cur_state.type);
if (dev)
{
monkey_dev_set_state(dev, &cur_state);
}
else
{
MONKEY_LOG_WARN("unsupport device type: %d", cur_state.type);
}
tick_elaps = monkey_tick_elaps(next_time_stamp, cur_time_stamp);
monkey_set_period(monkey, tick_elaps);
break;
default:
MONKEY_LOG_ERROR("error num_of_get = %d", num_of_get);
return false;
}
return true;
}
/****************************************************************************
* Name: monkey_update_uinput
****************************************************************************/
static bool monkey_update_uinput(FAR struct monkey_s *monkey)
{
bool retval = false;
MONKEY_ASSERT_NULL(monkey);
if (monkey->mode == MONKEY_MODE_RANDOM)
{
retval = monkey_update_uinput_ramdom(monkey);
}
else if(monkey->mode == MONKEY_MODE_PLAYBACK)
{
retval = monkey_update_uinput_playback(monkey);
}
else
{
MONKEY_LOG_ERROR("error mode: %d", monkey->mode);
}
return retval;
}
/****************************************************************************
* Name: monkey_update_input
****************************************************************************/
static bool monkey_update_input(FAR struct monkey_s *monkey)
{
struct monkey_dev_state_s state;
int available;
int i;
MONKEY_ASSERT_NULL(monkey);
available = monkey_dev_get_available(monkey->devs, monkey->dev_num);
if (available <= 0)
{
MONKEY_LOG_WARN("no available device");
return false;
}
for (i = 0; i < monkey->dev_num; i++)
{
FAR struct monkey_dev_s *dev = monkey->devs[i];
if (dev->is_available)
{
/* try to get device state */
if (!monkey_dev_get_state(dev, &state))
{
MONKEY_LOG_ERROR("can't get state");
return false;
}
if (dev->type == MONKEY_DEV_TYPE_TOUCH)
{
MONKEY_LOG_INFO("touch %s at x = %d, y = %d",
state.data.touch.is_pressed
? "PRESS " : "RELEASE",
state.data.touch.x, state.data.touch.y);
}
else if (dev->type == MONKEY_DEV_TYPE_BUTTON)
{
MONKEY_LOG_INFO("btn = 0x%08X", state.data.button.value);
}
/* record state */
if (monkey->recorder)
{
monkey_recorder_write(monkey->recorder, &state);
}
}
}
return true;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_update
****************************************************************************/
int monkey_update(FAR struct monkey_s *monkey)
{
int wait_time;
MONKEY_ASSERT_NULL(monkey);
srand(monkey_tick_get());
if (monkey->mode == MONKEY_MODE_RECORD)
{
if (monkey_update_input(monkey))
{
/* no need for sleep */
return 0;
}
else
{
return -1;
}
}
else
{
if (!monkey_update_uinput(monkey))
{
return -1;
}
}
wait_time = monkey_random(monkey->config.period.min,
monkey->config.period.max);
return wait_time;
}

View file

@ -0,0 +1,348 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_recorder.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "monkey_assert.h"
#include "monkey_log.h"
#include "monkey_dev.h"
#include "monkey_recorder.h"
#include "monkey_utils.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MONKEY_REC_HEAD_FMT "T%" PRIu32 ",D%X,"
#define MONKEY_REC_TOUCH_FMT MONKEY_REC_HEAD_FMT "X%d,Y%d,PR%d\n"
#define MONKEY_REC_BTN_FMT MONKEY_REC_HEAD_FMT "V%" PRIu32 "\n"
#define MONKEY_REC_FILE_EXT ".csv"
#define MONKEY_REC_FILE_HEAD "rec_"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_recorder_gen_file_path
****************************************************************************/
static void monkey_recorder_gen_file_path(FAR char *path_buf,
size_t buf_size,
FAR const char *dir_path)
{
char localtime_str_buf[64];
monkey_get_localtime_str(localtime_str_buf, sizeof(localtime_str_buf));
snprintf(path_buf, buf_size,
"%s/" MONKEY_REC_FILE_HEAD "%s" MONKEY_REC_FILE_EXT,
dir_path,
localtime_str_buf);
}
/****************************************************************************
* Name: monkey_readline
****************************************************************************/
static int monkey_readline(int fd, FAR char *ptr, int maxlen)
{
int n;
int rc;
char c;
for (n = 1; n < maxlen; n++)
{
if ((rc = read(fd, &c, 1)) == 1)
{
*ptr++ = c;
if (c == '\n')
{
break;
}
}
else if (rc == 0)
{
if (n == 1)
{
/* EOF no data read */
return 0;
}
else
{
/* EOF, some data read */
break;
}
}
else
{
/* error */
return -1;
}
}
*ptr = 0;
return n;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_recorder_create
****************************************************************************/
FAR struct monkey_recorder_s *monkey_recorder_create(FAR const char *path,
enum monkey_recorder_mode_e mode)
{
char file_path[PATH_MAX];
FAR const char *path_ptr;
int oflag;
int fd;
FAR struct monkey_recorder_s *recorder;
MONKEY_ASSERT_NULL(path);
recorder = calloc(1, sizeof(struct monkey_recorder_s));
MONKEY_ASSERT_NULL(recorder);
if (mode == MONKEY_RECORDER_MODE_RECORD)
{
if (!monkey_dir_check(path))
{
goto failed;
}
monkey_recorder_gen_file_path(file_path,
sizeof(file_path),
path);
path_ptr = file_path;
oflag = O_WRONLY | O_CREAT;
}
else
{
path_ptr = path;
oflag = O_RDONLY;
}
fd = open(path_ptr, oflag, 0666);
if (fd < 0)
{
MONKEY_LOG_ERROR("open %s failed: %d", path_ptr, errno);
goto failed;
}
recorder->fd = fd;
recorder->mode = mode;
MONKEY_LOG_NOTICE("open %s success, fd = %d, mode = %d",
path_ptr, fd, mode);
return recorder;
failed:
if (fd > 0)
{
close(fd);
}
if (recorder)
{
free(recorder);
}
return NULL;
}
/****************************************************************************
* Name: monkey_recorder_delete
****************************************************************************/
void monkey_recorder_delete(FAR struct monkey_recorder_s *recorder)
{
MONKEY_ASSERT_NULL(recorder);
if (recorder->fd > 0)
{
MONKEY_LOG_NOTICE("close fd: %d", recorder->fd);
close(recorder->fd);
}
free(recorder);
}
/****************************************************************************
* Name: monkey_recorder_write
****************************************************************************/
enum monkey_recorder_res_e monkey_recorder_write(
FAR struct monkey_recorder_s *recorder,
FAR const struct monkey_dev_state_s *state)
{
char buffer[128];
int len = -1;
int ret;
uint32_t cur_tick;
MONKEY_ASSERT_NULL(recorder);
MONKEY_ASSERT(recorder->mode == MONKEY_RECORDER_MODE_RECORD);
cur_tick = monkey_tick_get();
switch (MONKEY_GET_DEV_TYPE(state->type))
{
case MONKEY_DEV_TYPE_TOUCH:
len = snprintf(buffer, sizeof(buffer), MONKEY_REC_TOUCH_FMT,
cur_tick,
state->type,
state->data.touch.x,
state->data.touch.y,
state->data.touch.is_pressed);
break;
case MONKEY_DEV_TYPE_BUTTON:
len = snprintf(buffer, sizeof(buffer), MONKEY_REC_BTN_FMT,
cur_tick,
state->type,
state->data.button.value);
break;
default:
return MONKEY_RECORDER_RES_DEV_TYPE_ERROR;
}
if (len <= 0)
{
return MONKEY_RECORDER_RES_PARSER_ERROR;
}
ret = write(recorder->fd, buffer, len);
if (ret < 0)
{
return MONKEY_RECORDER_RES_WRITE_ERROR;
}
return MONKEY_RECORDER_RES_OK;
}
/****************************************************************************
* Name: monkey_recorder_read
****************************************************************************/
enum monkey_recorder_res_e monkey_recorder_read(
FAR struct monkey_recorder_s *recorder,
FAR struct monkey_dev_state_s *state,
FAR uint32_t *time_stamp)
{
char buffer[128];
int dev_type;
int converted;
int ret;
MONKEY_ASSERT_NULL(recorder);
MONKEY_ASSERT(recorder->mode == MONKEY_RECORDER_MODE_PLAYBACK);
ret = monkey_readline(recorder->fd, buffer, sizeof(buffer));
if (ret < 0)
{
return MONKEY_RECORDER_RES_READ_ERROR;
}
if (ret == 0)
{
return MONKEY_RECORDER_RES_END_OF_FILE;
}
/* Read head to get device type */
converted = sscanf(buffer, MONKEY_REC_HEAD_FMT, time_stamp, &dev_type);
if (converted != 2)
{
return MONKEY_RECORDER_RES_PARSER_ERROR;
}
state->type = dev_type;
/* Get data */
switch (MONKEY_GET_DEV_TYPE(state->type))
{
case MONKEY_DEV_TYPE_TOUCH:
converted = sscanf(buffer,
MONKEY_REC_TOUCH_FMT,
time_stamp,
&dev_type,
&state->data.touch.x,
&state->data.touch.y,
&state->data.touch.is_pressed);
if (converted != 5)
{
return MONKEY_RECORDER_RES_PARSER_ERROR;
}
break;
case MONKEY_DEV_TYPE_BUTTON:
converted = sscanf(buffer,
MONKEY_REC_BTN_FMT,
time_stamp,
&dev_type,
&state->data.button.value);
if (converted != 3)
{
return MONKEY_RECORDER_RES_PARSER_ERROR;
}
break;
default:
return MONKEY_RECORDER_RES_DEV_TYPE_ERROR;
}
return MONKEY_RECORDER_RES_OK;
}
/****************************************************************************
* Name: monkey_recorder_reset
****************************************************************************/
enum monkey_recorder_res_e monkey_recorder_reset(
FAR struct monkey_recorder_s *recorder)
{
MONKEY_ASSERT_NULL(recorder);
lseek(recorder->fd, 0, SEEK_SET);
return MONKEY_RECORDER_RES_OK;
}

View file

@ -0,0 +1,112 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_recorder.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_RECORDER_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_RECORDER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "monkey_type.h"
/****************************************************************************
* Public Types
****************************************************************************/
enum monkey_recorder_mode_e
{
MONKEY_RECORDER_MODE_RECORD,
MONKEY_RECORDER_MODE_PLAYBACK
};
struct monkey_recorder_s
{
int fd;
enum monkey_recorder_mode_e mode;
};
enum monkey_recorder_res_e
{
MONKEY_RECORDER_RES_OK,
MONKEY_RECORDER_RES_END_OF_FILE,
MONKEY_RECORDER_RES_DEV_TYPE_ERROR,
MONKEY_RECORDER_RES_WRITE_ERROR,
MONKEY_RECORDER_RES_READ_ERROR,
MONKEY_RECORDER_RES_PARSER_ERROR
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: monkey_recorder_create
****************************************************************************/
FAR struct monkey_recorder_s *monkey_recorder_create(FAR const char *path,
enum monkey_recorder_mode_e mode);
/****************************************************************************
* Name: monkey_recorder_delete
****************************************************************************/
void monkey_recorder_delete(FAR struct monkey_recorder_s *recorder);
/****************************************************************************
* Name: monkey_recorder_write
****************************************************************************/
enum monkey_recorder_res_e monkey_recorder_write(
FAR struct monkey_recorder_s *recorder,
FAR const struct monkey_dev_state_s *state);
/****************************************************************************
* Name: monkey_recorder_read
****************************************************************************/
enum monkey_recorder_res_e monkey_recorder_read(
FAR struct monkey_recorder_s *recorder,
FAR struct monkey_dev_state_s *state,
FAR uint32_t *time_stamp);
/****************************************************************************
* Name: monkey_recorder_reset
****************************************************************************/
enum monkey_recorder_res_e monkey_recorder_reset(
FAR struct monkey_recorder_s *recorder);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_RECORDER_H */

View file

@ -0,0 +1,134 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_type.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_TYPE_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_TYPE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MONKEY_UINPUT_TYPE_MASK (0x10)
#define MONKEY_IS_UINPUT_TYPE(type) (!!((type) & MONKEY_UINPUT_TYPE_MASK))
#define MONKEY_GET_DEV_TYPE(type) ((type) & ~MONKEY_UINPUT_TYPE_MASK)
#define MONKEY_DEV_MAX_NUM 2
/****************************************************************************
* Public Types
****************************************************************************/
struct monkey_dev_s;
struct monkey_recorder_s;
enum monkey_mode_e
{
MONKEY_MODE_RANDOM,
MONKEY_MODE_RECORD,
MONKEY_MODE_PLAYBACK,
};
enum monkey_dev_type_e
{
MONKEY_DEV_TYPE_UNKNOW = 0x00,
MONKEY_DEV_TYPE_TOUCH = 0x01,
MONKEY_DEV_TYPE_BUTTON = 0x02,
MONKEY_DEV_TYPE_UTOUCH = MONKEY_UINPUT_TYPE_MASK | MONKEY_DEV_TYPE_TOUCH,
MONKEY_DEV_TYPE_UBUTTON = MONKEY_UINPUT_TYPE_MASK | MONKEY_DEV_TYPE_BUTTON,
};
enum monkey_event_e
{
MONKEY_EVENT_CLICK,
MONKEY_EVENT_LONG_PRESS,
MONKEY_EVENT_DRAG,
MONKEY_EVENT_LAST
};
struct monkey_dev_state_s
{
enum monkey_dev_type_e type;
union
{
struct
{
int x;
int y;
int is_pressed;
} touch;
struct
{
uint32_t value;
} button;
} data;
};
struct monkey_event_config_s
{
int weight;
int duration_min;
int duration_max;
};
struct monkey_config_s
{
struct
{
int x_offset;
int y_offset;
int hor_res;
int ver_res;
} screen;
struct
{
uint32_t min;
uint32_t max;
} period;
uint8_t btn_bit;
struct monkey_event_config_s event[MONKEY_EVENT_LAST];
};
struct monkey_s
{
struct monkey_config_s config;
enum monkey_mode_e mode;
FAR struct monkey_dev_s *devs[MONKEY_DEV_MAX_NUM];
int dev_num;
FAR struct monkey_recorder_s *recorder;
struct
{
struct monkey_dev_state_s state;
uint32_t time_stamp;
} playback_ctx;
};
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_TYPE_H */

View file

@ -0,0 +1,258 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_utils.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "monkey_log.h"
#include "monkey_utils.h"
/****************************************************************************
* Private Types
****************************************************************************/
struct monkey_port_dev_type_name_s
{
enum monkey_dev_type_e type;
FAR const char *name;
};
/****************************************************************************
* Private Data
****************************************************************************/
static const struct monkey_port_dev_type_name_s g_type_name_grp[] =
{
{ MONKEY_DEV_TYPE_TOUCH, "touch" },
{ MONKEY_DEV_TYPE_BUTTON, "button" },
{ MONKEY_DEV_TYPE_UTOUCH, "utouch" },
{ MONKEY_DEV_TYPE_UBUTTON, "ubutton" }
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: monkey_random
****************************************************************************/
int monkey_random(int min, int max)
{
if (min >= max)
{
return min;
}
long diff = max - min + 1;
return rand() % diff + min;
}
/****************************************************************************
* Name: monkey_tick_get
****************************************************************************/
uint32_t monkey_tick_get(void)
{
struct timespec ts;
uint32_t ms;
clock_gettime(CLOCK_MONOTONIC, &ts);
ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
return ms;
}
/****************************************************************************
* Name: monkey_tick_elaps
****************************************************************************/
uint32_t monkey_tick_elaps(uint32_t act_time, uint32_t prev_tick)
{
/* If there is no overflow in sys_time simple subtract */
if (act_time >= prev_tick)
{
prev_tick = act_time - prev_tick;
}
else
{
prev_tick = UINT32_MAX - prev_tick + 1;
prev_tick += act_time;
}
return prev_tick;
}
/****************************************************************************
* Name: monkey_get_localtime_str
****************************************************************************/
void monkey_get_localtime_str(FAR char *str_buf, size_t buf_size)
{
time_t rawtime;
FAR struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
snprintf(str_buf, buf_size, "%04d%02d%02d_%02d%02d%02d",
1900 + timeinfo->tm_year,
timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour,
timeinfo->tm_min, timeinfo->tm_sec);
}
/****************************************************************************
* Name: monkey_dir_check
****************************************************************************/
bool monkey_dir_check(FAR const char *dir_path)
{
bool retval = false;
if (access(dir_path, F_OK) == 0)
{
MONKEY_LOG_NOTICE("directory: %s already exists", dir_path);
retval = true;
}
else
{
MONKEY_LOG_WARN("can't access directory: %s, creating...", dir_path);
if (mkdir(dir_path, 0777) == 0)
{
MONKEY_LOG_NOTICE("OK");
retval = true;
}
else
{
MONKEY_LOG_ERROR("create directory: %s failed", dir_path);
}
}
return retval;
}
/****************************************************************************
* Name: monkey_map
****************************************************************************/
int monkey_map(int x, int min_in, int max_in, int min_out, int max_out)
{
if (max_in >= min_in && x >= max_in)
{
return max_out;
}
if (max_in >= min_in && x <= min_in)
{
return min_out;
}
if (max_in <= min_in && x <= max_in)
{
return max_out;
}
if (max_in <= min_in && x >= min_in)
{
return min_out;
}
/* The equation should be:
* ((x - min_in) * delta_out) / delta in) + min_out
* To avoid rounding error reorder the operations:
* (x - min_in) * (delta_out / delta_min) + min_out
*/
int delta_in = max_in - min_in;
int delta_out = max_out - min_out;
return ((x - min_in) * delta_out) / delta_in + min_out;
}
/****************************************************************************
* Name: monkey_dev_type2name
****************************************************************************/
FAR const char *monkey_dev_type2name(enum monkey_dev_type_e type)
{
int i;
const int grp_len = sizeof(g_type_name_grp)
/ sizeof(struct monkey_port_dev_type_name_s);
for (i = 0; i < grp_len; i++)
{
if (type == g_type_name_grp[i].type)
{
return g_type_name_grp[i].name;
}
}
return "unknow";
}
/****************************************************************************
* Name: monkey_dev_name2type
****************************************************************************/
enum monkey_dev_type_e monkey_dev_name2type(FAR const char *name)
{
int i;
const int grp_len = sizeof(g_type_name_grp)
/ sizeof(struct monkey_port_dev_type_name_s);
if (name)
{
for (i = 0; i < grp_len; i++)
{
if (strcmp(name, g_type_name_grp[i].name) == 0)
{
return g_type_name_grp[i].type;
}
}
}
return MONKEY_DEV_TYPE_UNKNOW;
}
/****************************************************************************
* Name: monkey_event_type2name
****************************************************************************/
FAR const char *monkey_event_type2name(enum monkey_event_e event)
{
switch (event)
{
case MONKEY_EVENT_CLICK:
return "click";
case MONKEY_EVENT_LONG_PRESS:
return "long-press";
case MONKEY_EVENT_DRAG:
return "drag";
default:
break;
}
return "unknow";
}

View file

@ -0,0 +1,108 @@
/****************************************************************************
* apps/graphics/input/monkey/monkey_utils.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_UTILS_H
#define __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_UTILS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stddef.h>
#include "monkey_type.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: monkey_random
****************************************************************************/
int monkey_random(int min, int max);
/****************************************************************************
* Name: monkey_tick_get
****************************************************************************/
uint32_t monkey_tick_get(void);
/****************************************************************************
* Name: monkey_tick_elaps
****************************************************************************/
uint32_t monkey_tick_elaps(uint32_t act_time, uint32_t prev_tick);
/****************************************************************************
* Name: monkey_get_localtime_str
****************************************************************************/
void monkey_get_localtime_str(FAR char *str_buf, size_t buf_size);
/****************************************************************************
* Name: monkey_dir_check
****************************************************************************/
bool monkey_dir_check(FAR const char *dir_path);
/****************************************************************************
* Name: monkey_map
****************************************************************************/
int monkey_map(int x, int min_in, int max_in, int min_out, int max_out);
/****************************************************************************
* Name: monkey_dev_type2name
****************************************************************************/
FAR const char *monkey_dev_type2name(enum monkey_dev_type_e type);
/****************************************************************************
* Name: monkey_dev_name2type
****************************************************************************/
enum monkey_dev_type_e monkey_dev_name2type(FAR const char *name);
/****************************************************************************
* Name: monkey_event_type2name
****************************************************************************/
FAR const char *monkey_event_type2name(enum monkey_event_e event);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_GRAPHICS_INPUT_MONKEY_MONKEY_UTILS_H */