diff --git a/drivers/input/button_upper.c b/drivers/input/button_upper.c index 4107f5a453..b6899be301 100644 --- a/drivers/input/button_upper.c +++ b/drivers/input/button_upper.c @@ -129,6 +129,11 @@ static int btn_ioctl(FAR struct file *filep, int cmd, static int btn_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); +#ifdef CONFIG_INPUT_UINPUT +static ssize_t btn_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -138,7 +143,11 @@ static const struct file_operations btn_fops = btn_open, /* open */ btn_close, /* close */ btn_read, /* read */ +#ifdef CONFIG_INPUT_UINPUT + btn_write, /* write */ +#else NULL, /* write */ +#endif NULL, /* seek */ btn_ioctl, /* ioctl */ btn_poll /* poll */ @@ -508,7 +517,7 @@ static ssize_t btn_read(FAR struct file *filep, FAR char *buffer, if (len < sizeof(btn_buttonset_t)) { - ierr("ERROR: buffer too small: %lu\n", (unsigned long)len); + ierr("ERROR: buffer too small: %zu\n", len); return -EINVAL; } @@ -531,6 +540,64 @@ static ssize_t btn_read(FAR struct file *filep, FAR char *buffer, return (ssize_t)sizeof(btn_buttonset_t); } +/**************************************************************************** + * Name: btn_write + ****************************************************************************/ + +#ifdef CONFIG_INPUT_UINPUT + +static ssize_t btn_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct btn_upperhalf_s *priv; + FAR const struct btn_lowerhalf_s *lower; + int ret; + + DEBUGASSERT(filep && filep->f_inode); + inode = filep->f_inode; + DEBUGASSERT(inode->i_private); + priv = (FAR struct btn_upperhalf_s *)inode->i_private; + + /* Make sure that the buffer is sufficiently large to hold at least one + * complete sample. + * + * REVISIT: Should also check buffer alignment. + */ + + if (buflen < sizeof(btn_buttonset_t)) + { + ierr("ERROR: buffer too small: %zu\n", buflen); + return -EINVAL; + } + + /* Get exclusive access to the driver structure */ + + ret = btn_takesem(&priv->bu_exclsem); + if (ret < 0) + { + ierr("ERROR: btn_takesem failed: %d\n", ret); + return ret; + } + + /* Write the current state of the buttons */ + + lower = priv->bu_lower; + DEBUGASSERT(lower); + if (lower->bl_write) + { + ret = lower->bl_write(lower, buffer, buflen); + } + else + { + ret = -ENOSYS; + } + + btn_givesem(&priv->bu_exclsem); + return (ssize_t)ret; +} +#endif + /**************************************************************************** * Name: btn_ioctl ****************************************************************************/ diff --git a/drivers/input/uinput.c b/drivers/input/uinput.c index 47dd9e08c5..f78d780b9d 100644 --- a/drivers/input/uinput.c +++ b/drivers/input/uinput.c @@ -26,9 +26,10 @@ #include #include -#include +#include #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -36,17 +37,50 @@ #define UINPUT_NAME_SIZE 32 +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct uinput_button_lowerhalf_s +{ + struct btn_lowerhalf_s lower; + btn_buttonset_t buttons; + btn_handler_t handler; + FAR void *arg; +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ +#ifdef CONFIG_INPUT_TOUCHSCREEN static ssize_t uinput_touch_write(FAR struct touch_lowerhalf_s *lower, FAR const char *buffer, size_t buflen); +#endif + +#ifdef CONFIG_INPUT_BUTTONS +static ssize_t uinput_button_write(FAR const struct btn_lowerhalf_s *lower, + FAR const char *buffer, size_t buflen); + +static btn_buttonset_t uinput_button_supported(FAR const struct + btn_lowerhalf_s *lower); + +static btn_buttonset_t uinput_button_buttons(FAR const struct + btn_lowerhalf_s *lower); + +static void uinput_button_enable(FAR const struct btn_lowerhalf_s *lower, + btn_buttonset_t press, + btn_buttonset_t release, + btn_handler_t handler, + FAR void *arg); +#endif /**************************************************************************** * Private Functions ****************************************************************************/ +#ifdef CONFIG_INPUT_TOUCHSCREEN + /**************************************************************************** * Name: uinput_touch_write ****************************************************************************/ @@ -65,6 +99,65 @@ static ssize_t uinput_touch_write(FAR struct touch_lowerhalf_s *lower, touch_event(lower->priv, sample); return buflen; } +#endif /* CONFIG_INPUT_TOUCHSCREEN */ + +#ifdef CONFIG_INPUT_BUTTONS + +/**************************************************************************** + * Name: uinput_button_write + ****************************************************************************/ + +static ssize_t uinput_button_write(FAR const struct btn_lowerhalf_s *lower, + FAR const char *buffer, size_t buflen) +{ + FAR struct uinput_button_lowerhalf_s *ubtn_lower = + (FAR struct uinput_button_lowerhalf_s *)lower; + + if (buflen != sizeof(btn_buttonset_t)) + { + return -EINVAL; + } + + ubtn_lower->buttons = *(btn_buttonset_t *)buffer; + ubtn_lower->handler(&ubtn_lower->lower, ubtn_lower->arg); + + return buflen; +} + +/**************************************************************************** + * Name: uinput_button_supported + ****************************************************************************/ + +static btn_buttonset_t uinput_button_supported(FAR const struct + btn_lowerhalf_s *lower) +{ + return ~0u; +} + +/**************************************************************************** + * Name: uinput_button_buttons + ****************************************************************************/ + +static btn_buttonset_t +uinput_button_buttons(FAR const struct btn_lowerhalf_s *lower) +{ + FAR struct uinput_button_lowerhalf_s *ubtn_lower = + (FAR struct uinput_button_lowerhalf_s *)lower; + return ubtn_lower->buttons; +} + +static void uinput_button_enable(FAR const struct btn_lowerhalf_s *lower, + btn_buttonset_t press, + btn_buttonset_t release, + btn_handler_t handler, FAR void *arg) +{ + FAR struct uinput_button_lowerhalf_s *ubtn_lower = + (FAR struct uinput_button_lowerhalf_s *)lower; + ubtn_lower->arg = arg; + ubtn_lower->handler = handler; +} + +#endif /* CONFIG_INPUT_BUTTONS */ /**************************************************************************** * Public Functions @@ -106,3 +199,20 @@ int uinput_touch_initialize(FAR const char *name, int maxpoint, int buffnums) return touch_register(lower, devname, buffnums); } + +#ifdef CONFIG_INPUT_BUTTONS +int uinput_button_initialize(FAR const char *name) +{ + char devname[UINPUT_NAME_SIZE]; + FAR struct uinput_button_lowerhalf_s *ubtn_lower; + + ubtn_lower = kmm_zalloc(sizeof(struct uinput_button_lowerhalf_s)); + ubtn_lower->lower.bl_buttons = uinput_button_buttons; + ubtn_lower->lower.bl_enable = uinput_button_enable; + ubtn_lower->lower.bl_supported = uinput_button_supported; + ubtn_lower->lower.bl_write = uinput_button_write; + + snprintf(devname, UINPUT_NAME_SIZE, "/dev/%s", name); + return btn_register(devname, &ubtn_lower->lower); +} +#endif /* CONFIG_INPUT_BUTTONS */ diff --git a/include/nuttx/input/buttons.h b/include/nuttx/input/buttons.h index c98c80ac72..757ac28d31 100644 --- a/include/nuttx/input/buttons.h +++ b/include/nuttx/input/buttons.h @@ -148,6 +148,11 @@ struct btn_lowerhalf_s CODE void (*bl_enable)(FAR const struct btn_lowerhalf_s *lower, btn_buttonset_t press, btn_buttonset_t release, btn_handler_t handler, FAR void *arg); + + /* Key write callback function */ + + CODE ssize_t (*bl_write)(FAR const struct btn_lowerhalf_s *lower, + FAR const char *buffer, size_t buflen); }; /**************************************************************************** diff --git a/include/nuttx/input/uinput.h b/include/nuttx/input/uinput.h index 46e777212e..f55afba943 100644 --- a/include/nuttx/input/uinput.h +++ b/include/nuttx/input/uinput.h @@ -49,4 +49,21 @@ int uinput_touch_initialize(FAR const char *name, int maxpoint, int buffnums); +/**************************************************************************** + * Name: uinput_button_initialize + * + * Description: + * Initialized the uinput button device + * + * Input Parameters: + * name: Button devices name + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int uinput_button_initialize(FAR const char *name); + #endif /* __INCLUDE_NUTTX_INPUT_UINPUT_H */