This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 7a2d5bbc64271ae43b86afde64e35a695962a236 Author: Zhe Weng <weng...@xiaomi.com> AuthorDate: Tue Mar 11 20:08:58 2025 +0800 apps/graphics: Add input generator library We can use it to unify our monkey / input tools, and for other input generation purposes easily. Signed-off-by: Zhe Weng <weng...@xiaomi.com> --- graphics/input/CMakeLists.txt | 27 ++ graphics/input/Kconfig | 11 + graphics/input/Make.defs | 25 ++ graphics/input/Makefile | 29 ++ graphics/input/generator/input_gen_ctx.c | 304 ++++++++++++++ graphics/input/generator/input_gen_dev.c | 228 ++++++++++ graphics/input/generator/input_gen_event.c | 578 ++++++++++++++++++++++++++ graphics/input/generator/input_gen_internal.h | 174 ++++++++ include/graphics/input_gen.h | 304 ++++++++++++++ 9 files changed, 1680 insertions(+) diff --git a/graphics/input/CMakeLists.txt b/graphics/input/CMakeLists.txt new file mode 100644 index 000000000..17d86c80c --- /dev/null +++ b/graphics/input/CMakeLists.txt @@ -0,0 +1,27 @@ +# ############################################################################## +# apps/graphics/input/CMakeLists.txt +# +# 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. +# +# ############################################################################## + +if(CONFIG_GRAPHICS_INPUT_GENERATOR) + nuttx_add_library(input_generator) + file(GLOB CSRCS generator/*.c) + target_sources(input_generator PRIVATE ${CSRCS}) +endif() diff --git a/graphics/input/Kconfig b/graphics/input/Kconfig new file mode 100644 index 000000000..f4358da94 --- /dev/null +++ b/graphics/input/Kconfig @@ -0,0 +1,11 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config GRAPHICS_INPUT_GENERATOR + bool "Input generator library" + default n + ---help--- + This is a simple input generator library that can be used to + generate input events for testing graphics applications. diff --git a/graphics/input/Make.defs b/graphics/input/Make.defs new file mode 100644 index 000000000..8bf4cb9c1 --- /dev/null +++ b/graphics/input/Make.defs @@ -0,0 +1,25 @@ +############################################################################ +# apps/graphics/input/Make.defs +# +# 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. +# +############################################################################ + +ifneq ($(CONFIG_GRAPHICS_INPUT_GENERATOR),) +CONFIGURED_APPS += $(APPDIR)/graphics/input +endif diff --git a/graphics/input/Makefile b/graphics/input/Makefile new file mode 100644 index 000000000..2fc9e696f --- /dev/null +++ b/graphics/input/Makefile @@ -0,0 +1,29 @@ +############################################################################ +# apps/graphics/input/Makefile +# +# 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. +# +############################################################################ + +include $(APPDIR)/Make.defs + +ifneq ($(CONFIG_GRAPHICS_INPUT_GENERATOR),) +CSRCS = $(wildcard generator/*.c) +endif + +include $(APPDIR)/Application.mk diff --git a/graphics/input/generator/input_gen_ctx.c b/graphics/input/generator/input_gen_ctx.c new file mode 100644 index 000000000..6449979fd --- /dev/null +++ b/graphics/input/generator/input_gen_ctx.c @@ -0,0 +1,304 @@ +/**************************************************************************** + * apps/graphics/input/generator/input_gen_ctx.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 <debug.h> +#include <errno.h> +#include <stdlib.h> +#include <strings.h> +#include <sys/file.h> +#include <sys/types.h> + +#include "input_gen_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct input_gen_ctx_s +{ + struct input_gen_dev_s devs[INPUT_GEN_DEV_NUM]; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: input_gen_create + * + * Description: + * Create an input generator context. + * + * Input Parameters: + * ctx - A pointer to the input generator context, or NULL if the + * context failed to be created. + * devices - Device types to be opened. + * + * Returned Value: + * Success device count. On failure, a negated errno value is returned. + * + ****************************************************************************/ + +int input_gen_create(FAR input_gen_ctx_t *ctx, uint32_t devices) +{ + int success = 0; + int i; + + if (ctx == NULL || devices & ~INPUT_GEN_DEV_ALL) + { + gerr("ERROR: Invalid parameter: ctx=%p, devices=0x%08" PRIX32 "\n", + ctx, devices); + return -EINVAL; + } + + *ctx = (input_gen_ctx_t)zalloc(sizeof(struct input_gen_ctx_s)); + if (*ctx == NULL) + { + return -ENOMEM; + } + + /* Initialize the device context */ + + for (i = 0; i < INPUT_GEN_DEV_NUM; i++) + { + FAR struct input_gen_dev_s *dev = &(*ctx)->devs[i]; + input_gen_dev_t current = (1 << i); + + if (devices & current) + { + dev->fd = open(input_gen_dev2path(current), + O_WRONLY | O_NONBLOCK); + if (dev->fd < 0) + { + dev->device = INPUT_GEN_DEV_NONE; + gerr("ERROR: Open %s failed: %d\n", + input_gen_dev2path(current), errno); + continue; + } + + ginfo("Opened %s, fd = %d\n", + input_gen_dev2path(current), dev->fd); + dev->device = current; + success++; + } + else + { + dev->fd = -1; + dev->device = INPUT_GEN_DEV_NONE; + } + } + + ginfo("%d devices opened\n", success); + + if (success == 0) + { + free(*ctx); + *ctx = NULL; + return -ENODEV; + } + + return success; +} + +/**************************************************************************** + * Name: input_gen_destroy + * + * Description: + * Destroy an input generator context. + * + * Input Parameters: + * ctx - The input generator context to destroy. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_destroy(input_gen_ctx_t ctx) +{ + int i; + + if (ctx == NULL) + { + return -EINVAL; + } + + for (i = 0; i < INPUT_GEN_DEV_NUM; i++) + { + if (ctx->devs[i].fd >= 0) + { + ginfo("Closing %s, fd = %d\n", + input_gen_dev2path(ctx->devs[i].device), ctx->devs[i].fd); + close(ctx->devs[i].fd); + } + } + + free(ctx); + return OK; +} + +/**************************************************************************** + * Name: input_gen_search_dev + * + * Description: + * Get the input generator device by type. + * + * Input Parameters: + * ctx - The input generator context. + * device - The device type. + * + * Returned Value: + * A pointer to the input generator device structure, or NULL if not found. + * + ****************************************************************************/ + +FAR struct input_gen_dev_s *input_gen_search_dev(input_gen_ctx_t ctx, + input_gen_dev_t device) +{ + int i; + + if (ctx == NULL || device > INPUT_GEN_DEV_ALL) + { + return NULL; + } + + for (i = 0; i < INPUT_GEN_DEV_NUM; i++) + { + if (ctx->devs[i].device & device) + { + return &ctx->devs[i]; + } + } + + nwarn("WARNING: Device with type %d not found\n", device); + return NULL; +} + +/**************************************************************************** + * Name: input_gen_query_device + * + * Description: + * Query whether the device with the specified type is opened. + * + * Input Parameters: + * ctx - The input generator context. + * device - The device type. + * + * Returned Value: + * True if the device is opened, false otherwise. + * + ****************************************************************************/ + +bool input_gen_query_device(input_gen_ctx_t ctx, input_gen_dev_t device) +{ + return input_gen_search_dev(ctx, device) != NULL; +} + +/**************************************************************************** + * Name: input_gen_reset_devices + * + * Description: + * Reset the device state with the specified type. + * + * Input Parameters: + * ctx - The input generator context. + * devices - The device types to reset state. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_reset_devices(input_gen_ctx_t ctx, uint32_t devices) +{ + int ret; + + if (ctx == NULL) + { + return -EINVAL; + } + + /* Use actions with duration 0 to reset the device state */ + + if (devices & INPUT_GEN_DEV_UTOUCH) + { + ret = input_gen_swipe(ctx, 0, 0, 0, 0, 0); + if (ret < 0 && ret != -ENODEV) + { + return ret; + } + } + + if (devices & INPUT_GEN_DEV_UBUTTON) + { + ret = input_gen_button_longpress(ctx, 0, 0); + if (ret < 0 && ret != -ENODEV) + { + return ret; + } + } + + /* TODO: Reset keyboard when we support it. */ + + return OK; +} + +/**************************************************************************** + * Name: input_gen_write_raw + * + * Description: + * Write raw data to the device. + * + * Input Parameters: + * ctx - The input generator context. + * device - The device type. + * buf - The buffer to write. + * nbytes - The number of bytes to write. + * + * Returned Value: + * The number of bytes written, or a negated errno value on failure. + * + ****************************************************************************/ + +ssize_t input_gen_write_raw(input_gen_ctx_t ctx, input_gen_dev_t device, + FAR const void *buf, size_t nbytes) +{ + FAR struct input_gen_dev_s *dev = input_gen_search_dev(ctx, device); + ssize_t ret; + + if (dev == NULL) + { + gerr("ERROR: Device with type %d not found\n", device); + return -ENODEV; + } + + ret = write(dev->fd, buf, nbytes); + return ret < 0 ? -errno : ret; +} diff --git a/graphics/input/generator/input_gen_dev.c b/graphics/input/generator/input_gen_dev.c new file mode 100644 index 000000000..117946d9c --- /dev/null +++ b/graphics/input/generator/input_gen_dev.c @@ -0,0 +1,228 @@ +/**************************************************************************** + * apps/graphics/input/generator/input_gen_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 <nuttx/config.h> + +#include <debug.h> +#include <sys/file.h> +#include <sys/ioctl.h> + +#include <nuttx/input/mouse.h> + +#include "input_gen_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define INPUT_GEN_DEV_PATH_UTOUCH "/dev/utouch" +#define INPUT_GEN_DEV_PATH_UBUTTON "/dev/ubutton" +#define INPUT_GEN_DEV_PATH_UMOUSE "/dev/umouse" +#define INPUT_GEN_DEV_PATH_UKEYBOARD "/dev/ukeyboard" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: input_gen_dev2path + * + * Description: + * Convert device type to device path. + * + * Input Parameters: + * device - Device type + * + * Returned Value: + * Device path string. + * + ****************************************************************************/ + +FAR const char *input_gen_dev2path(input_gen_dev_t device) +{ + switch (device) + { + case INPUT_GEN_DEV_UTOUCH: + return INPUT_GEN_DEV_PATH_UTOUCH; + case INPUT_GEN_DEV_UBUTTON: + return INPUT_GEN_DEV_PATH_UBUTTON; + case INPUT_GEN_DEV_UMOUSE: + return INPUT_GEN_DEV_PATH_UMOUSE; + case INPUT_GEN_DEV_UKEYBOARD: + return INPUT_GEN_DEV_PATH_UKEYBOARD; + default: + gerr("ERROR: Invalid device type: %d\n", device); + return ""; + } +} + +/**************************************************************************** + * Name: input_gen_utouch_write + * + * Description: + * Write touch sample to the device. + * + * Input Parameters: + * fd - File descriptor of the device + * sample - Pointer to the touch sample structure + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_utouch_write(int fd, FAR const struct touch_sample_s *sample) +{ + size_t nbytes = SIZEOF_TOUCH_SAMPLE_S(sample->npoints); + ssize_t ret = write(fd, sample, nbytes); + + if (ret != nbytes) + { + gerr("ERROR: utouch_write failed: nbytes = %zu, ret = %zd, error = %d," + " data = %d points, first at x = %d, y = %d, pressure = %u\n", + nbytes, ret, errno, sample->npoints, sample->point[0].x, + sample->point[0].y, sample->point[0].pressure); + return ret < 0 ? -errno : -EIO; + } + + ginfo("utouch_write: %d points, first at x = %d, y = %d, pressure = %u\n", + sample->npoints, sample->point[0].x, sample->point[0].y, + sample->point[0].pressure); + return OK; +} + +/**************************************************************************** + * Name: input_gen_ubutton_write + * + * Description: + * Write button state to the device. + * + * Input Parameters: + * fd - File descriptor of the device + * mask - Button mask + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_ubutton_write(int fd, btn_buttonset_t mask) +{ + ssize_t ret = write(fd, &mask, sizeof(mask)); + + if (ret != sizeof(mask)) + { + gerr("ERROR: ubutton_write failed: %zd, error = %d\n", ret, errno); + return ret < 0 ? -errno : -EIO; + } + + ginfo("ubutton_write: mask = 0x%08" PRIX32 "\n", mask); + return OK; +} + +/**************************************************************************** + * Name: input_gen_umouse_write + * + * Description: + * Write mouse wheel state to the device. + * + * Input Parameters: + * fd - File descriptor of the device + * wheel - Mouse wheel value + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +#ifdef CONFIG_INPUT_MOUSE_WHEEL +int input_gen_umouse_write(int fd, int16_t wheel) +{ + struct mouse_report_s sample; + ssize_t ret; + + memset(&sample, 0, sizeof(sample)); + sample.wheel = wheel; + + ret = write(fd, &sample, sizeof(sample)); + if (ret != sizeof(sample)) + { + gerr("ERROR: umouse_write failed: %zd, error = %d\n", ret, errno); + return ret < 0 ? -errno : -EIO; + } + + ginfo("umouse_write: wheel = %d\n", wheel); + return OK; +} +#endif + +/**************************************************************************** + * Name: input_gen_grab / input_gen_ungrab + * + * Description: + * Grab or ungrab the input device. + * + * Input Parameters: + * dev - The input generator device. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_grab(FAR struct input_gen_dev_s *dev) +{ +/* Note: We use flock instead of GRAB ioctl because GRAB will block user + * programs like LVGL from receiving events from the device. + */ + +#if CONFIG_FS_LOCK_BUCKET_SIZE > 0 + if (flock(dev->fd, LOCK_EX | LOCK_NB) < 0) + { + gerr("ERROR: input_gen_grab failed: %d\n", errno); + return -errno; + } +#endif + + return OK; +} + +int input_gen_ungrab(FAR struct input_gen_dev_s *dev) +{ +#if CONFIG_FS_LOCK_BUCKET_SIZE > 0 + if (flock(dev->fd, LOCK_UN) < 0) + { + gerr("ERROR: input_gen_ungrab failed: %d\n", errno); + return -errno; + } +#endif + + return OK; +} diff --git a/graphics/input/generator/input_gen_event.c b/graphics/input/generator/input_gen_event.c new file mode 100644 index 000000000..d2de2b77f --- /dev/null +++ b/graphics/input/generator/input_gen_event.c @@ -0,0 +1,578 @@ +/**************************************************************************** + * apps/graphics/input/generator/input_gen_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 <nuttx/config.h> + +#include <debug.h> +#include <stdint.h> +#include <unistd.h> + +#include "input_gen_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define INPUT_GEN_DEFAULT_PRESSURE 42 + +#define INPUT_GEN_DEFAULT_PRESS_DURATION 50 /* ms */ +#define INPUT_GEN_DEFAULT_HOLD_DURATION 5 /* ms */ + +#define INPUT_GEN_DEFAULT_CLICK_DURATION 100 /* ms */ + +#define INPUT_GEN_MAX_FINGERS 2 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Structure to hold parameters for single finger operations, we can support + * multiple fingers by using multiple instances of this structure. + */ + +struct input_gen_single_finger_s +{ + int16_t x1; + int16_t y1; + int16_t x2; + int16_t y2; + uint32_t press_duration; + uint32_t move_duration; + uint32_t hold_duration; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: input_gen_tick_get + * + * Description: + * Get the current tick count in milliseconds. + * + * Returned Value: + * The current tick count in milliseconds. + * + ****************************************************************************/ + +static uint32_t input_gen_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: input_gen_tick_elapsed + * + * Description: + * Calculate the elapsed time in milliseconds since the last tick. + * + * Input Parameters: + * act_time - The current tick count. + * prev_tick - The previous tick count. + * + * Returned Value: + * The elapsed time in milliseconds. + * + ****************************************************************************/ + +static uint32_t input_gen_tick_elapsed(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: input_gen_single_finger + * + * Description: + * Calculate the position of a single finger based on the elapsed time and + * the parameters. + * + * Input Parameters: + * point - The touch point structure to fill in. + * finger - The parameters for the single finger operation. + * elapsed - The elapsed time since the start of the operation. + * + * Returned Value: + * True if the operation is finished, false otherwise. + * + ****************************************************************************/ + +static bool +input_gen_single_finger(FAR struct touch_point_s *point, + FAR const struct input_gen_single_finger_s *finger, + uint32_t elapsed) +{ + if (elapsed < finger->press_duration) + { + /* Press */ + + input_gen_fill_point(point, finger->x1, finger->y1, TOUCH_DOWN); + return false; + } + + elapsed -= finger->press_duration; + if (elapsed < finger->move_duration) + { + int16_t x = ((int64_t)(finger->x2 - finger->x1) * elapsed) / + finger->move_duration + finger->x1; + int16_t y = ((int64_t)(finger->y2 - finger->y1) * elapsed) / + finger->move_duration + finger->y1; + input_gen_fill_point(point, x, y, TOUCH_MOVE); + + return false; + } + + elapsed -= finger->move_duration; + if (elapsed < finger->hold_duration) + { + /* Hold */ + + input_gen_fill_point(point, finger->x2, finger->y2, TOUCH_DOWN); + return false; + } + + /* Release */ + + input_gen_fill_point(point, finger->x2, finger->y2, TOUCH_UP); + return true; +} + +/**************************************************************************** + * Name: input_gen_write_motion + * + * Description: + * Write a motion event to the device. + * + * Input Parameters: + * fd - The file descriptor of the device. + * fingers - The parameters for the motion operation. + * nfingers - The number of fingers. + * elapsed - The elapsed time since the start of the operation. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +static int input_gen_write_motion(int fd, + FAR const struct input_gen_single_finger_s *fingers, + size_t nfingers, uint32_t elapsed) +{ + size_t finished = 0; + size_t i; + int ret; + union /* A union with enough space to make compiler / checker happy. */ + { + struct touch_sample_s sample; + struct + { + uint8_t placeholder[offsetof(struct touch_sample_s, point)]; + struct touch_point_s point[INPUT_GEN_MAX_FINGERS]; + } points; + } buffer; + + /* Check the number of fingers */ + + if (nfingers < 1 || nfingers > INPUT_GEN_MAX_FINGERS) + { + return -EINVAL; + } + + /* Fill the touch sample structure */ + + buffer.sample.npoints = nfingers; + + for (i = 0; i < nfingers; i++) + { + FAR struct touch_point_s *point = &buffer.points.point[i]; + + point->id = i; + if (input_gen_single_finger(point, &fingers[i], elapsed)) + { + finished++; + } + + ginfo("Finger %zu: x = %d, y = %d, flags = %02X\n", + i, point->x, point->y, point->flags); + } + + /* Write the sample to the device */ + + ret = input_gen_utouch_write(fd, &buffer.sample); + if (ret < 0) + { + return ret; + } + + return finished == nfingers ? OK : -EAGAIN; +} + +/**************************************************************************** + * Name: input_gen_motion + * + * Description: + * Perform a motion operation. + * + * Input Parameters: + * ctx - The input generator context. + * fingers - The parameters for the motion operation. + * nfingers - The number of fingers. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +static int input_gen_motion(input_gen_ctx_t ctx, + FAR const struct input_gen_single_finger_s *fingers, + size_t nfingers) +{ + FAR struct input_gen_dev_s *dev; + uint32_t start; + int ret; + + dev = input_gen_search_dev(ctx, INPUT_GEN_DEV_UTOUCH); + if (dev == NULL) + { + return -ENODEV; + } + + ret = input_gen_grab(dev); + if (ret < 0) + { + return ret; + } + + start = input_gen_tick_get(); + + do + { + uint32_t elapsed = input_gen_tick_elapsed(input_gen_tick_get(), start); + ret = input_gen_write_motion(dev->fd, fingers, nfingers, elapsed); + if (ret == -EAGAIN && usleep(1000) < 0) + { + nwarn("WARNING: Maybe interrupted by signal\n"); + input_gen_ungrab(dev); + return -errno; + } + } + while (ret == -EAGAIN); + + input_gen_ungrab(dev); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: input_gen_tap + * + * Description: + * Perform a tap operation. + * + * Input Parameters: + * ctx - The input generator context. + * x - The x coordinate. + * y - The y coordinate. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_tap(input_gen_ctx_t ctx, int16_t x, int16_t y) +{ + struct input_gen_single_finger_s finger = + { + .x1 = x, + .y1 = y, + .x2 = x, + .y2 = y, + .press_duration = INPUT_GEN_DEFAULT_PRESS_DURATION, + .move_duration = 0, + .hold_duration = 0, + }; + + return input_gen_motion(ctx, &finger, 1); +} + +/**************************************************************************** + * Name: input_gen_drag / input_gen_swipe + * + * Description: + * Perform a drag or swipe operation. + * + * Input Parameters: + * ctx - The input generator context. + * x1 - The start x coordinate. + * y1 - The start y coordinate. + * x2 - The end x coordinate. + * y2 - The end y coordinate. + * duration - The duration of the operation. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_drag(input_gen_ctx_t ctx, int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint32_t duration) +{ + struct input_gen_single_finger_s finger = + { + .x1 = x1, + .y1 = y1, + .x2 = x2, + .y2 = y2, + .press_duration = INPUT_GEN_DEFAULT_PRESS_DURATION, + .move_duration = duration, + .hold_duration = INPUT_GEN_DEFAULT_HOLD_DURATION, + }; + + return input_gen_motion(ctx, &finger, 1); +} + +int input_gen_swipe(input_gen_ctx_t ctx, int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint32_t duration) +{ + struct input_gen_single_finger_s finger = + { + .x1 = x1, + .y1 = y1, + .x2 = x2, + .y2 = y2, + .press_duration = 0, + .move_duration = duration, + .hold_duration = 0, + }; + + return input_gen_motion(ctx, &finger, 1); +} + +/**************************************************************************** + * Name: input_gen_pinch + * + * Description: + * Perform a pinch operation. + * + * Input Parameters: + * ctx - The input generator context. + * x1_start - The start x coordinate of the first finger. + * y1_start - The start y coordinate of the first finger. + * x2_start - The start x coordinate of the second finger. + * y2_start - The start y coordinate of the second finger. + * x1_end - The end x coordinate of the first finger. + * y1_end - The end y coordinate of the first finger. + * x2_end - The end x coordinate of the second finger. + * y2_end - The end y coordinate of the second finger. + * duration - The duration of the operation. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_pinch(input_gen_ctx_t ctx, int16_t x1_start, int16_t y1_start, + int16_t x2_start, int16_t y2_start, int16_t x1_end, + int16_t y1_end, int16_t x2_end, int16_t y2_end, + uint32_t duration) +{ + struct input_gen_single_finger_s fingers[2] = + { + { + .x1 = x1_start, + .y1 = y1_start, + .x2 = x1_end, + .y2 = y1_end, + .press_duration = INPUT_GEN_DEFAULT_PRESS_DURATION, + .move_duration = duration, + .hold_duration = INPUT_GEN_DEFAULT_HOLD_DURATION, + }, + { + .x1 = x2_start, + .y1 = y2_start, + .x2 = x2_end, + .y2 = y2_end, + .press_duration = INPUT_GEN_DEFAULT_PRESS_DURATION, + .move_duration = duration, + .hold_duration = INPUT_GEN_DEFAULT_HOLD_DURATION, + }, + }; + + return input_gen_motion(ctx, fingers, 2); +} + +/**************************************************************************** + * Name: input_gen_button_click / input_gen_button_longpress + * + * Description: + * Perform a button click or long press operation. + * + * Input Parameters: + * ctx - The input generator context. + * mask - The button mask. + * duration - The duration of the operation. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_button_click(input_gen_ctx_t ctx, btn_buttonset_t mask) +{ + return input_gen_button_longpress(ctx, mask, + INPUT_GEN_DEFAULT_CLICK_DURATION); +} + +int input_gen_button_longpress(input_gen_ctx_t ctx, btn_buttonset_t mask, + uint32_t duration) +{ + FAR struct input_gen_dev_s *dev; + int ret; + + dev = input_gen_search_dev(ctx, INPUT_GEN_DEV_UBUTTON); + if (dev == NULL) + { + return -ENODEV; + } + + ret = input_gen_grab(dev); + if (ret < 0) + { + return ret; + } + + ret = input_gen_ubutton_write(dev->fd, mask); + if (ret < 0) + { + goto out; + } + + usleep(duration * 1000); + + ret = input_gen_ubutton_write(dev->fd, 0); + if (ret < 0) + { + goto out; + } + +out: + input_gen_ungrab(dev); + return ret; +} + +/**************************************************************************** + * Name: input_gen_mouse_wheel + * + * Description: + * Perform a mouse wheel operation. + * + * Input Parameters: + * ctx - The input generator context. + * wheel - The wheel value. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +#ifdef CONFIG_INPUT_MOUSE_WHEEL +int input_gen_mouse_wheel(input_gen_ctx_t ctx, int16_t wheel) +{ + FAR struct input_gen_dev_s *dev; + + dev = input_gen_search_dev(ctx, INPUT_GEN_DEV_UMOUSE); + if (dev == NULL) + { + return -ENODEV; + } + + return input_gen_umouse_write(dev->fd, wheel); +} +#endif + +/**************************************************************************** + * Name: input_gen_fill_point + * + * Description: + * Fill the touch point structure. + * + * Input Parameters: + * point - The touch point structure. + * x - The x coordinate. + * y - The y coordinate. + * flags - The TOUCH_DOWN, TOUCH_MOVE, TOUCH_UP flag. + * + ****************************************************************************/ + +void input_gen_fill_point(FAR struct touch_point_s *point, + int16_t x, int16_t y, uint8_t flags) +{ + point->x = x; + point->y = y; + point->h = 1; + point->w = 1; + + if (flags & TOUCH_UP) + { + point->pressure = 0; + point->flags = flags | TOUCH_ID_VALID; + } + else + { + point->pressure = INPUT_GEN_DEFAULT_PRESSURE; + point->flags = flags | TOUCH_ID_VALID | TOUCH_POS_VALID | + TOUCH_PRESSURE_VALID; + } +} diff --git a/graphics/input/generator/input_gen_internal.h b/graphics/input/generator/input_gen_internal.h new file mode 100644 index 000000000..8fadec865 --- /dev/null +++ b/graphics/input/generator/input_gen_internal.h @@ -0,0 +1,174 @@ +/**************************************************************************** + * apps/graphics/input/generator/input_gen_internal.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_GENERATOR_INPUT_GEN_INTERNAL_H +#define __APPS_GRAPHICS_INPUT_GENERATOR_INPUT_GEN_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/input/touchscreen.h> + +#include <graphics/input_gen.h> + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct input_gen_dev_s +{ + int fd; + input_gen_dev_t device; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: input_gen_search_dev + * + * Description: + * Get the input generator device by type. + * + * Input Parameters: + * ctx - The input generator context. + * device - The device type. + * + * Returned Value: + * A pointer to the input generator device structure, or NULL if not found. + * + ****************************************************************************/ + +FAR struct input_gen_dev_s *input_gen_search_dev(input_gen_ctx_t ctx, + input_gen_dev_t device); + +/**************************************************************************** + * Name: input_gen_dev2path + * + * Description: + * Convert device type to device path. + * + * Input Parameters: + * device - Device type + * + * Returned Value: + * Device path string. + * + ****************************************************************************/ + +FAR const char *input_gen_dev2path(input_gen_dev_t device); + +/**************************************************************************** + * Name: input_gen_utouch_write + * + * Description: + * Write touch sample to the device. + * + * Input Parameters: + * fd - File descriptor of the device + * sample - Pointer to the touch sample structure + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_utouch_write(int fd, FAR const struct touch_sample_s *sample); + +/**************************************************************************** + * Name: input_gen_ubutton_write + * + * Description: + * Write button state to the device. + * + * Input Parameters: + * fd - File descriptor of the device + * mask - Button mask + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_ubutton_write(int fd, btn_buttonset_t mask); + +/**************************************************************************** + * Name: input_gen_umouse_write + * + * Description: + * Write mouse wheel state to the device. + * + * Input Parameters: + * fd - File descriptor of the device + * wheel - Mouse wheel value + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +#ifdef CONFIG_INPUT_MOUSE_WHEEL +int input_gen_umouse_write(int fd, int16_t wheel); +#endif + +/**************************************************************************** + * Name: input_gen_grab / input_gen_ungrab + * + * Description: + * Grab or ungrab the input device. + * + * Input Parameters: + * dev - The input generator device. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_grab(FAR struct input_gen_dev_s *dev); +int input_gen_ungrab(FAR struct input_gen_dev_s *dev); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __APPS_GRAPHICS_INPUT_GENERATOR_INPUT_GEN_INTERNAL_H */ diff --git a/include/graphics/input_gen.h b/include/graphics/input_gen.h new file mode 100644 index 000000000..b69f4d69a --- /dev/null +++ b/include/graphics/input_gen.h @@ -0,0 +1,304 @@ +/**************************************************************************** + * apps/include/graphics/input_gen.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_INCLUDE_GRAPHICS_INPUT_GEN_H +#define __APPS_INCLUDE_GRAPHICS_INPUT_GEN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> + +#include <nuttx/input/buttons.h> +#include <nuttx/input/touchscreen.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define INPUT_GEN_DEV_NUM 4 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Device types */ + +typedef enum +{ + INPUT_GEN_DEV_NONE = 0x00, + INPUT_GEN_DEV_UTOUCH = 0x01, /* Touchscreen */ + INPUT_GEN_DEV_UBUTTON = 0x02, /* Button */ + INPUT_GEN_DEV_UMOUSE = 0x04, /* Mouse */ + INPUT_GEN_DEV_UKEYBOARD = 0x08, /* Keyboard */ + INPUT_GEN_DEV_ALL = INPUT_GEN_DEV_UTOUCH | INPUT_GEN_DEV_UBUTTON | + INPUT_GEN_DEV_UMOUSE | INPUT_GEN_DEV_UKEYBOARD +} input_gen_dev_t; + +/* Input generator context */ + +typedef FAR struct input_gen_ctx_s *input_gen_ctx_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: input_gen_create + * + * Description: + * Create an input generator context. + * + * Input Parameters: + * ctx - A pointer to the input generator context, or NULL if the + * context failed to be created. + * devices - Device types to be opened. + * + * Returned Value: + * Success device count. On failure, a negated errno value is returned. + * + ****************************************************************************/ + +int input_gen_create(FAR input_gen_ctx_t *ctx, uint32_t devices); + +/**************************************************************************** + * Name: input_gen_destroy + * + * Description: + * Destroy an input generator context. + * + * Input Parameters: + * ctx - The input generator context to destroy. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_destroy(input_gen_ctx_t ctx); + +/**************************************************************************** + * Name: input_gen_query_device + * + * Description: + * Query whether the device with the specified type is opened. + * + * Input Parameters: + * ctx - The input generator context. + * device - The device type. + * + * Returned Value: + * True if the device is opened, false otherwise. + * + ****************************************************************************/ + +bool input_gen_query_device(input_gen_ctx_t ctx, input_gen_dev_t device); + +/**************************************************************************** + * Name: input_gen_reset_devices + * + * Description: + * Reset the device state with the specified type. + * + * Input Parameters: + * ctx - The input generator context. + * devices - The device types to reset state. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_reset_devices(input_gen_ctx_t ctx, uint32_t devices); + +/**************************************************************************** + * Name: input_gen_tap + * + * Description: + * Perform a tap operation. + * + * Input Parameters: + * ctx - The input generator context. + * x - The x coordinate. + * y - The y coordinate. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_tap(input_gen_ctx_t ctx, int16_t x, int16_t y); + +/**************************************************************************** + * Name: input_gen_drag / input_gen_swipe + * + * Description: + * Perform a drag or swipe operation. + * + * Input Parameters: + * ctx - The input generator context. + * x1 - The start x coordinate. + * y1 - The start y coordinate. + * x2 - The end x coordinate. + * y2 - The end y coordinate. + * duration - The duration of the operation. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_drag(input_gen_ctx_t ctx, int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint32_t duration); +int input_gen_swipe(input_gen_ctx_t ctx, int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint32_t duration); + +/**************************************************************************** + * Name: input_gen_pinch + * + * Description: + * Perform a pinch operation. + * + * Input Parameters: + * ctx - The input generator context. + * x1_start - The start x coordinate of the first finger. + * y1_start - The start y coordinate of the first finger. + * x2_start - The start x coordinate of the second finger. + * y2_start - The start y coordinate of the second finger. + * x1_end - The end x coordinate of the first finger. + * y1_end - The end y coordinate of the first finger. + * x2_end - The end x coordinate of the second finger. + * y2_end - The end y coordinate of the second finger. + * duration - The duration of the operation. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_pinch(input_gen_ctx_t ctx, int16_t x1_start, int16_t y1_start, + int16_t x2_start, int16_t y2_start, int16_t x1_end, + int16_t y1_end, int16_t x2_end, int16_t y2_end, + uint32_t duration); + +/**************************************************************************** + * Name: input_gen_button_click / input_gen_button_longpress + * + * Description: + * Perform a button click or long press operation. + * + * Input Parameters: + * ctx - The input generator context. + * mask - The button mask. + * duration - The duration of the operation. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +int input_gen_button_click(input_gen_ctx_t ctx, btn_buttonset_t mask); +int input_gen_button_longpress(input_gen_ctx_t ctx, btn_buttonset_t mask, + uint32_t duration); + +/**************************************************************************** + * Name: input_gen_mouse_wheel + * + * Description: + * Perform a mouse wheel operation. + * + * Input Parameters: + * ctx - The input generator context. + * wheel - The wheel value. + * + * Returned Value: + * Zero (OK) is returned on success. On failure, a negated errno value is + * returned. + * + ****************************************************************************/ + +#ifdef CONFIG_INPUT_MOUSE_WHEEL +int input_gen_mouse_wheel(input_gen_ctx_t ctx, int16_t wheel); +#else +#define input_gen_mouse_wheel(ctx, wheel) (-ENODEV) +#endif + +/**************************************************************************** + * Name: input_gen_fill_point + * + * Description: + * Fill the touch point structure. + * + * Input Parameters: + * point - The touch point structure. + * x - The x coordinate. + * y - The y coordinate. + * flags - The TOUCH_DOWN, TOUCH_MOVE, TOUCH_UP flag. + * + ****************************************************************************/ + +void input_gen_fill_point(FAR struct touch_point_s *point, + int16_t x, int16_t y, uint8_t flags); + +/**************************************************************************** + * Name: input_gen_write_raw + * + * Description: + * Write raw data to the device. + * + * Input Parameters: + * ctx - The input generator context. + * device - The device type. + * buf - The buffer to write. + * nbytes - The number of bytes to write. + * + * Returned Value: + * The number of bytes written, or a negated errno value on failure. + * + ****************************************************************************/ + +ssize_t input_gen_write_raw(input_gen_ctx_t ctx, input_gen_dev_t device, + FAR const void *buf, size_t nbytes); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_GRAPHICS_INPUT_GEN_H */