326 lines
8.5 KiB
C
326 lines
8.5 KiB
C
/****************************************************************************
|
|
* apps/testing/monkey/monkey_dev.c
|
|
*
|
|
* 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;
|
|
}
|