diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 2605191a47..abf5153e0d 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -41,6 +41,14 @@ config INPUT_UINPUT ---help--- Enable support virtual input device driver +config UINPUT_RPMSG + bool "Enable uinput rpmsg" + depends on INPUT_UINPUT + depends on RPTUN + default n + ---help--- + Enable support uinput cross core communication + config UINPUT_TOUCHSCREEN bool "Enable uinput touchscreen" select INPUT_TOUCHSCREEN diff --git a/drivers/input/uinput.c b/drivers/input/uinput.c index 78aa743d96..457b278e6f 100644 --- a/drivers/input/uinput.c +++ b/drivers/input/uinput.c @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -28,19 +30,58 @@ #include #include #include +#include + +#ifdef CONFIG_UINPUT_RPMSG +# include +#endif /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#define UINPUT_NAME_SIZE 32 +#define UINPUT_NAME_SIZE 16 +#define RPMSG_UINPUT_NAME "rpmsg-uinput-%s" /**************************************************************************** * Private Types ****************************************************************************/ +#ifdef CONFIG_UINPUT_RPMSG + +struct uinput_rpmsg_ept_s +{ + struct rpmsg_endpoint ept; + struct rpmsg_device *rdev; + struct list_node node; +}; + +struct uinput_context_s +{ + char name[UINPUT_NAME_SIZE]; + struct list_node eptlist; + ssize_t (*notify)(FAR void *uinput_lower, + FAR const char *buffer, + size_t buflen); +}; + +#endif /* CONFIG_UINPUT_RPMSG */ + +struct uinput_touch_lowerhalf_s +{ +#ifdef CONFIG_UINPUT_RPMSG + struct uinput_context_s ctx; +#endif + + struct touch_lowerhalf_s lower; +}; + struct uinput_button_lowerhalf_s { +#ifdef CONFIG_UINPUT_RPMSG + struct uinput_context_s ctx; +#endif + struct btn_lowerhalf_s lower; btn_buttonset_t buttons; btn_handler_t handler; @@ -51,8 +92,31 @@ struct uinput_button_lowerhalf_s * Private Function Prototypes ****************************************************************************/ +#ifdef CONFIG_UINPUT_RPMSG + +static int uinput_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static void uinput_rpmsg_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv); + +static void uinput_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv); + +static int uinput_rpmsg_initialize(FAR struct uinput_context_s *ctx, + FAR const char *name); + +static void uinput_rpmsg_notify(FAR struct uinput_context_s *ctx, + FAR const char *buffer, size_t buflen); + +#endif /* CONFIG_UINPUT_RPMSG */ + #ifdef CONFIG_UINPUT_TOUCHSCREEN +static ssize_t uinput_touch_notify(FAR void *uinput_lower, + FAR const char *buffer, size_t buflen); + static ssize_t uinput_touch_write(FAR struct touch_lowerhalf_s *lower, FAR const char *buffer, size_t buflen); @@ -60,6 +124,9 @@ static ssize_t uinput_touch_write(FAR struct touch_lowerhalf_s *lower, #ifdef CONFIG_UINPUT_BUTTONS +static ssize_t uinput_button_notify(FAR void *uinput_lower, + FAR const char *buffer, size_t buflen); + static ssize_t uinput_button_write(FAR const struct btn_lowerhalf_s *lower, FAR const char *buffer, size_t buflen); @@ -81,8 +148,137 @@ static void uinput_button_enable(FAR const struct btn_lowerhalf_s *lower, * Private Functions ****************************************************************************/ +#ifdef CONFIG_UINPUT_RPMSG + +/**************************************************************************** + * uinput_rpmsg_ept_cb + ****************************************************************************/ + +static int uinput_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct uinput_context_s *ctx = priv; + + ctx->notify(ctx, data, len); + return 0; +} + +/**************************************************************************** + * uinput_rpmsg_device_created + ****************************************************************************/ + +static void uinput_rpmsg_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv) +{ + int ret; + char rpmsg_ept_name[RPMSG_NAME_SIZE]; + FAR struct uinput_rpmsg_ept_s *ept; + FAR struct uinput_context_s *ctx = (FAR struct uinput_context_s *)priv; + FAR struct list_node *list = &ctx->eptlist; + + ept = kmm_zalloc(sizeof(struct uinput_rpmsg_ept_s)); + if (ept == NULL) + { + ierr("Failed to alloc memory\n"); + return; + } + + ept->ept.priv = ctx; + snprintf(rpmsg_ept_name, sizeof(rpmsg_ept_name), + RPMSG_UINPUT_NAME, ctx->name); + ret = rpmsg_create_ept(&ept->ept, rdev, rpmsg_ept_name, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + uinput_rpmsg_ept_cb, NULL); + if (ret < 0) + { + ierr("uinput rpmsg create failure, %s\n", rpmsg_get_cpuname(rdev)); + kmm_free(ept); + return; + } + + ept->rdev = rdev; + list_add_tail(list, &ept->node); +} + +/**************************************************************************** + * uinput_rpmsg_device_destroy + ****************************************************************************/ + +static void uinput_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv) +{ + FAR struct uinput_context_s *ctx = (FAR struct uinput_context_s *)priv; + FAR struct list_node *list = &ctx->eptlist; + FAR struct uinput_rpmsg_ept_s *ept; + + list_for_every_entry(list, ept, struct uinput_rpmsg_ept_s, node) + { + if (ept->rdev == rdev) + { + list_delete(&ept->node); + rpmsg_destroy_ept(priv); + kmm_free(ept); + return; + } + } +} + +/**************************************************************************** + * Name: uinput_rpmsg_initialize + ****************************************************************************/ + +static int uinput_rpmsg_initialize(FAR struct uinput_context_s *ctx, + FAR const char *name) +{ + list_initialize(&ctx->eptlist); + strlcpy(ctx->name, name, UINPUT_NAME_SIZE); + return rpmsg_register_callback(ctx, uinput_rpmsg_device_created, + uinput_rpmsg_device_destroy, NULL); +} + +/**************************************************************************** + * Name: uinput_rpmsg_notify + ****************************************************************************/ + +static void uinput_rpmsg_notify(FAR struct uinput_context_s *ctx, + FAR const char *buffer, size_t buflen) +{ + FAR struct uinput_rpmsg_ept_s *ept; + + list_for_every_entry(&ctx->eptlist, ept, struct uinput_rpmsg_ept_s, node) + { + if (is_rpmsg_ept_ready(&ept->ept) == 0) + { + if (rpmsg_send(&ept->ept, buffer, buflen) < 0) + { + ierr("uinput rpmsg send failed, cpu : %s\n", + rpmsg_get_cpuname(ept->rdev)); + } + } + } +} + +#endif /* CONFIG_UINPUT_RPMSG */ + #ifdef CONFIG_UINPUT_TOUCHSCREEN +/**************************************************************************** + * Name: uinput_touch_notify + ****************************************************************************/ + +static ssize_t uinput_touch_notify(FAR void *uinput_lower, + FAR const char *buffer, size_t buflen) +{ + FAR struct uinput_touch_lowerhalf_s *utcs_lower = + (FAR struct uinput_touch_lowerhalf_s *)uinput_lower; + FAR const struct touch_sample_s *sample = + (FAR const struct touch_sample_s *)buffer; + + touch_event(utcs_lower->lower.priv, sample); + return buflen; +} + /**************************************************************************** * Name: uinput_touch_write ****************************************************************************/ @@ -90,22 +286,44 @@ static void uinput_button_enable(FAR const struct btn_lowerhalf_s *lower, static ssize_t uinput_touch_write(FAR struct touch_lowerhalf_s *lower, FAR const char *buffer, size_t buflen) { - FAR const struct touch_sample_s *sample; + FAR struct uinput_touch_lowerhalf_s *utcs_lower = + container_of(lower, struct uinput_touch_lowerhalf_s, lower); - sample = (FAR const struct touch_sample_s *)buffer; - if (sample == NULL) - { - return -EINVAL; - } +#ifdef CONFIG_UINPUT_RPMSG + uinput_rpmsg_notify(&utcs_lower->ctx, buffer, buflen); +#endif - touch_event(lower->priv, sample); - return buflen; + return uinput_touch_notify(utcs_lower, buffer, buflen); } #endif /* CONFIG_UINPUT_TOUCHSCREEN */ #ifdef CONFIG_UINPUT_BUTTONS +/**************************************************************************** + * Name: uinput_button_notify + ****************************************************************************/ + +static ssize_t uinput_button_notify(FAR void *uinput_lower, + FAR const char *buffer, size_t buflen) +{ + FAR struct uinput_button_lowerhalf_s *ubtn_lower = + (FAR struct uinput_button_lowerhalf_s *)uinput_lower; + + if (buflen != sizeof(btn_buttonset_t)) + { + return -EINVAL; + } + + ubtn_lower->buttons = *(btn_buttonset_t *)buffer; + if (ubtn_lower->handler != NULL) + { + ubtn_lower->handler(&ubtn_lower->lower, ubtn_lower->arg); + } + + return buflen; +} + /**************************************************************************** * Name: uinput_button_write ****************************************************************************/ @@ -114,25 +332,21 @@ 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; + container_of(lower, struct uinput_button_lowerhalf_s, lower); - if (buflen != sizeof(btn_buttonset_t)) - { - return -EINVAL; - } +#ifdef CONFIG_UINPUT_RPMSG + uinput_rpmsg_notify(&ubtn_lower->ctx, buffer, buflen); +#endif - ubtn_lower->buttons = *(btn_buttonset_t *)buffer; - ubtn_lower->handler(&ubtn_lower->lower, ubtn_lower->arg); - - return buflen; + return uinput_button_notify(ubtn_lower, buffer, buflen); } /**************************************************************************** * Name: uinput_button_supported ****************************************************************************/ -static btn_buttonset_t uinput_button_supported(FAR const struct - btn_lowerhalf_s *lower) +static btn_buttonset_t +uinput_button_supported(FAR const struct btn_lowerhalf_s *lower) { return ~0u; } @@ -145,8 +359,7 @@ 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; - + container_of(lower, struct uinput_button_lowerhalf_s, lower); return ubtn_lower->buttons; } @@ -160,8 +373,7 @@ static void uinput_button_enable(FAR const struct btn_lowerhalf_s *lower, btn_handler_t handler, FAR void *arg) { FAR struct uinput_button_lowerhalf_s *ubtn_lower = - (FAR struct uinput_button_lowerhalf_s *)lower; - + container_of(lower, struct uinput_button_lowerhalf_s, lower); ubtn_lower->arg = arg; ubtn_lower->handler = handler; } @@ -194,28 +406,36 @@ static void uinput_button_enable(FAR const struct btn_lowerhalf_s *lower, int uinput_touch_initialize(FAR const char *name, int maxpoint, int buffnums) { char devname[UINPUT_NAME_SIZE]; - FAR struct touch_lowerhalf_s *lower; + FAR struct uinput_touch_lowerhalf_s *utcs_lower; int ret; - lower = kmm_zalloc(sizeof(struct touch_lowerhalf_s)); - if (!lower) + utcs_lower = kmm_zalloc(sizeof(struct uinput_touch_lowerhalf_s)); + if (utcs_lower == NULL) { return -ENOMEM; } + utcs_lower->lower.write = uinput_touch_write; + utcs_lower->lower.maxpoint = maxpoint; +#ifdef CONFIG_UINPUT_RPMSG + utcs_lower->ctx.notify = uinput_touch_notify; +#endif + /* Regiest Touchscreen device */ - lower->write = uinput_touch_write; - lower->maxpoint = maxpoint; - - snprintf(devname, UINPUT_NAME_SIZE, "/dev/%s", name); - ret = touch_register(lower, devname, buffnums); + snprintf(devname, sizeof(devname), "/dev/%s", name); + ret = touch_register(&utcs_lower->lower, devname, buffnums); if (ret < 0) { - kmm_free(lower); + kmm_free(utcs_lower); + return ret; } - return ret; +#ifdef CONFIG_UINPUT_RPMSG + uinput_rpmsg_initialize(&utcs_lower->ctx, name); +#endif + + return 0; } #endif /* CONFIG_UINPUT_TOUCHSCREEN */ @@ -248,15 +468,24 @@ int uinput_button_initialize(FAR const char *name) ubtn_lower->lower.bl_enable = uinput_button_enable; ubtn_lower->lower.bl_supported = uinput_button_supported; ubtn_lower->lower.bl_write = uinput_button_write; +#ifdef CONFIG_UINPUT_RPMSG + ubtn_lower->ctx.notify = uinput_button_notify; +#endif - snprintf(devname, UINPUT_NAME_SIZE, "/dev/%s", name); + snprintf(devname, sizeof(devname), "/dev/%s", name); ret = btn_register(devname, &ubtn_lower->lower); if (ret < 0) { kmm_free(ubtn_lower); + ierr("ERROR: uinput button initialize failed\n"); + return ret; } - return ret; +#ifdef CONFIG_UINPUT_RPMSG + uinput_rpmsg_initialize(&ubtn_lower->ctx, name); +#endif + + return 0; } #endif /* CONFIG_UINPUT_BUTTONS */