drivers/input:support mouse driver

Implement mouse driver lower upper

Signed-off-by: liuhongchao <liuhongchao@xiaomi.com>
This commit is contained in:
liuhongchao 2023-07-13 18:58:05 +08:00 committed by Xiang Xiao
parent 99c2a6ffbe
commit 69b655f4b2
4 changed files with 440 additions and 9 deletions

View File

@ -27,6 +27,10 @@ if(CONFIG_INPUT)
list(APPEND SRCS touchscreen_upper.c)
endif()
if(CONFIG_INPUT_MOUSE)
list(APPEND SRCS mouse_upper.c)
endif()
if(CONFIG_INPUT_UINPUT)
list(APPEND SRCS uinput.c)
endif()

View File

@ -28,6 +28,10 @@ ifeq ($(CONFIG_INPUT_TOUCHSCREEN),y)
CSRCS += touchscreen_upper.c
endif
ifeq ($(CONFIG_INPUT_MOUSE),y)
CSRCS += mouse_upper.c
endif
ifeq ($(CONFIG_INPUT_TSC2007),y)
CSRCS += tsc2007.c
endif

363
drivers/input/mouse_upper.c Normal file
View File

@ -0,0 +1,363 @@
/****************************************************************************
* drivers/input/mouse_upper.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 <nuttx/config.h>
#include <debug.h>
#include <fcntl.h>
#include <poll.h>
#include <nuttx/input/mouse.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mutex.h>
#include <nuttx/list.h>
#include <nuttx/mm/circbuf.h>
/****************************************************************************
* Private Types
****************************************************************************/
struct mouse_openpriv_s
{
struct circbuf_s circbuf; /* Store mouse point data in circle buffer */
struct list_node node; /* Opened file buffer linked list node */
FAR struct pollfd *fds; /* Polling structure of waiting thread */
sem_t waitsem; /* Used to wait for the availability of data */
mutex_t lock; /* Manages exclusive access to this structure */
};
/* This structure is for mouse upper half driver */
struct mouse_upperhalf_s
{
uint8_t nums; /* Number of mouse point structure */
mutex_t lock; /* Manages exclusive access to this structure */
struct list_node head; /* Opened file buffer chain header node */
FAR struct mouse_lowerhalf_s *lower; /* A pointer of lower half instance */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int mouse_open(FAR struct file *filep);
static int mouse_close(FAR struct file *filep);
static ssize_t mouse_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static int mouse_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct file_operations g_mouse_fops =
{
mouse_open, /* open */
mouse_close, /* close */
mouse_read, /* read */
NULL, /* write */
NULL, /* seek */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
mouse_poll /* poll */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mouse_open
****************************************************************************/
static int mouse_open(FAR struct file *filep)
{
FAR struct mouse_openpriv_s *openpriv;
FAR struct inode *inode = filep->f_inode;
FAR struct mouse_upperhalf_s *upper = inode->i_private;
int ret;
ret = nxmutex_lock(&upper->lock);
if (ret < 0)
{
return ret;
}
openpriv = kmm_zalloc(sizeof(struct mouse_openpriv_s));
if (openpriv == NULL)
{
nxmutex_unlock(&upper->lock);
return -ENOMEM;
}
ret = circbuf_init(&openpriv->circbuf, NULL,
upper->nums * sizeof(struct mouse_report_s));
if (ret < 0)
{
kmm_free(openpriv);
nxmutex_unlock(&upper->lock);
return ret;
}
nxsem_init(&openpriv->waitsem, 0, 0);
nxmutex_init(&openpriv->lock);
list_add_tail(&upper->head, &openpriv->node);
/* Save the buffer node pointer so that it can be used directly
* in the read operation.
*/
filep->f_priv = openpriv;
nxmutex_unlock(&upper->lock);
return ret;
}
/****************************************************************************
* Name: mouse_close
****************************************************************************/
static int mouse_close(FAR struct file *filep)
{
FAR struct mouse_openpriv_s *openpriv = filep->f_priv;
FAR struct inode *inode = filep->f_inode;
FAR struct mouse_upperhalf_s *upper = inode->i_private;
int ret;
ret = nxmutex_lock(&upper->lock);
if (ret < 0)
{
return ret;
}
list_delete(&openpriv->node);
circbuf_uninit(&openpriv->circbuf);
nxsem_destroy(&openpriv->waitsem);
nxmutex_destroy(&openpriv->lock);
kmm_free(openpriv);
nxmutex_unlock(&upper->lock);
return ret;
}
/****************************************************************************
* Name: mouse_read
****************************************************************************/
static ssize_t mouse_read(FAR struct file *filep, FAR char *buffer,
size_t len)
{
FAR struct mouse_openpriv_s *openpriv = filep->f_priv;
ssize_t ret;
if (!buffer || !len)
{
return -EINVAL;
}
ret = nxmutex_lock(&openpriv->lock);
if (ret < 0)
{
return ret;
}
while (circbuf_is_empty(&openpriv->circbuf))
{
if (filep->f_oflags & O_NONBLOCK)
{
ret = -EAGAIN;
goto out;
}
else
{
nxmutex_unlock(&openpriv->lock);
ret = nxsem_wait_uninterruptible(&openpriv->waitsem);
if (ret < 0)
{
return ret;
}
ret = nxmutex_lock(&openpriv->lock);
if (ret < 0)
{
return ret;
}
}
}
ret = circbuf_read(&openpriv->circbuf, buffer, len);
out:
nxmutex_unlock(&openpriv->lock);
return ret;
}
/****************************************************************************
* Name: mouse_poll
****************************************************************************/
static int mouse_poll(FAR struct file *filep, struct pollfd *fds, bool setup)
{
FAR struct mouse_openpriv_s *openpriv = filep->f_priv;
pollevent_t eventset = 0;
int ret;
ret = nxmutex_lock(&openpriv->lock);
if (ret < 0)
{
return ret;
}
if (setup)
{
if (openpriv->fds == NULL)
{
openpriv->fds = fds;
fds->priv = &openpriv->fds;
}
else
{
ret = -EBUSY;
goto errout;
}
if (!circbuf_is_empty(&openpriv->circbuf))
{
eventset |= POLLIN;
}
poll_notify(&openpriv->fds, 1, eventset);
}
else if (fds->priv)
{
openpriv->fds = NULL;
fds->priv = NULL;
}
errout:
nxmutex_unlock(&openpriv->lock);
return ret;
}
/****************************************************************************
* Public Function
****************************************************************************/
/****************************************************************************
* Name: mouse_event
****************************************************************************/
void mouse_event(FAR void *priv, FAR const struct mouse_report_s *sample)
{
FAR struct mouse_upperhalf_s *upper = priv;
FAR struct mouse_openpriv_s *openpriv;
int semcount;
if (nxmutex_lock(&upper->lock) < 0)
{
return;
}
list_for_every_entry(&upper->head, openpriv, struct mouse_openpriv_s, node)
{
circbuf_overwrite(&openpriv->circbuf, sample,
sizeof(struct mouse_report_s));
nxsem_get_value(&openpriv->waitsem, &semcount);
if (semcount < 1)
{
nxsem_post(&openpriv->waitsem);
}
if (openpriv->fds && openpriv->fds->fd >= 0)
{
poll_notify(&openpriv->fds, 1, POLLIN);
}
}
nxmutex_unlock(&upper->lock);
}
/****************************************************************************
* Name: mouse_register
****************************************************************************/
int mouse_register(FAR struct mouse_lowerhalf_s *lower,
FAR const char *path, uint8_t nums)
{
FAR struct mouse_upperhalf_s *upper;
int ret;
iinfo("Registering %s\n", path);
if (lower == NULL || nums == 0)
{
ierr("ERROR: invalid mouse device\n");
return -EINVAL;
}
upper = kmm_zalloc(sizeof(struct mouse_upperhalf_s));
if (!upper)
{
ierr("ERROR: Failed to mem alloc!\n");
return -ENOMEM;
}
lower->priv = upper;
upper->lower = lower;
upper->nums = nums;
list_initialize(&upper->head);
nxmutex_init(&upper->lock);
ret = register_driver(path, &g_mouse_fops, 0666, upper);
if (ret < 0)
{
nxmutex_destroy(&upper->lock);
kmm_free(upper);
return ret;
}
return ret;
}
/****************************************************************************
* Name: mouse_unregister
****************************************************************************/
void mouse_unregister(FAR struct mouse_lowerhalf_s *lower,
FAR const char *path)
{
FAR struct mouse_upperhalf_s *upper;
DEBUGASSERT(lower != NULL);
DEBUGASSERT(lower->priv != NULL);
upper = lower->priv;
iinfo("UnRegistering %s\n", path);
unregister_driver(path);
nxmutex_destroy(&upper->lock);
kmm_free(upper);
}

View File

@ -47,19 +47,22 @@
#define MOUSE_BUTTON_1 (1 << 0) /* True: Left mouse button pressed */
#define MOUSE_BUTTON_2 (1 << 1) /* True: Right mouse button pressed */
#define MOUSE_BUTTON_3 (1 << 2) /* True: Middle mouse button pressed */
#define MOUSE_BUTTON_4 (1 << 3) /* True: Left mouse button released */
#define MOUSE_BUTTON_5 (1 << 4) /* True: Right mouse button released */
#define MOUSE_BUTTON_6 (1 << 5) /* True: Middle mouse button released */
/****************************************************************************
* Public Types
****************************************************************************/
/* This structure contains information about the current mouse button states
* and mouse position. Positional units are device specific and determined
* by mouse configuration settings.
/* This structure contains information about the current mouse button
* states and mouse position. Positional units are device specific
* and determined by mouseconfiguration settings.
*/
struct mouse_report_s
{
uint8_t buttons; /* See TOUCH_* definitions above */
uint8_t buttons; /* See MOUSE_* definitions above */
/* Possibly padded with 1 byte here */
int16_t x; /* X coordinate of the mouse position */
int16_t y; /* Y coordinate of the mouse position */
@ -68,10 +71,67 @@ struct mouse_report_s
#endif
};
/* This structure is for mouse lower half driver */
struct mouse_lowerhalf_s
{
FAR void *priv; /* Save the upper half pointer */
};
/****************************************************************************
* Public Data
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: mouse_event
*
* Description:
* The lower half driver pushes mouse events through this interface,
* provided by mouse upper half.
*
* Arguments:
* priv - Upper half driver handle.
* sample - pointer to data of mouse point event.
****************************************************************************/
void mouse_event(FAR void *priv, FAR const struct mouse_report_s *sample);
/****************************************************************************
* Name: mouse_register
*
* Description:
* This function registers a mouse device, the upper half binds
* with hardware device through the lower half instance.
*
* Arguments:
* lower - A pointer of lower half instance.
* path - The path of mouse device. such as "/dev/mouse0"
* nums - Number of the mouse points structure.
*
* Return:
* OK if the driver was successfully registered; A negated errno value is
* returned on any failure.
*
****************************************************************************/
int mouse_register(FAR struct mouse_lowerhalf_s *lower,
FAR const char *path, uint8_t nums);
/****************************************************************************
* Name: mouse_unregister
*
* Description:
* This function is used to mouse driver to unregister and
* release the occupied resources.
*
* Arguments:
* lower - A pointer to an insatnce of mouse lower half driver.
* path - The path of mouse device. such as "/dev/mouse0"
****************************************************************************/
void mouse_unregister(FAR struct mouse_lowerhalf_s *lower,
FAR const char *path);
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"