diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index dbb1c8d700..0886fe89f6 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -13,6 +13,15 @@ menuconfig INPUT if INPUT +config INPUT_GOLDFISH_EVENTS + bool "Goldfish input events driver" + default n + +config INPUT_GOLDFISH_NBUFFER + int "Number of goldfish events buffer" + depends on INPUT_GOLDFISH_EVENTS + default 8 + config INPUT_MOUSE bool default n diff --git a/drivers/input/Make.defs b/drivers/input/Make.defs index 48faabfcfe..e1b568f604 100644 --- a/drivers/input/Make.defs +++ b/drivers/input/Make.defs @@ -108,6 +108,10 @@ ifeq ($(CONFIG_INPUT_SPQ10KBD),y) CSRCS += spq10kbd.c endif +ifeq ($(CONFIG_INPUT_GOLDFISH_EVENTS),y) + CSRCS += goldfish_events.c +endif + # Include input device driver build support DEPPATH += --dep-path input diff --git a/drivers/input/goldfish_events.c b/drivers/input/goldfish_events.c new file mode 100644 index 0000000000..c040868295 --- /dev/null +++ b/drivers/input/goldfish_events.c @@ -0,0 +1,406 @@ +/**************************************************************************** + * drivers/input/goldfish_events.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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#ifndef putreg32 +#define putreg32(v, x) (*(volatile uint32_t *)(x) = (v)) +#endif + +#ifndef getreg32 +#define getreg32(x) (*(uint32_t *)(x)) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum +{ + GOLDFISH_EVENTS_READ = 0x00, /* Read next event type, code or value. */ + GOLDFISH_EVENTS_SET_PAGE = 0x00, /* Set page index. */ + GOLDFISH_EVENTS_LEN = 0x04, /* Read length of page data. */ + GOLDFISH_EVENTS_DATA = 0x08, /* Read page data. */ + + GOLDFISH_EVENTS_PAGE_NAME = 0x0000, /* Keyboard charmap name. */ + GOLDFISH_EVENTS_PAGE_EVBITS = 0x10000, /* Event code supported sets. */ + GOLDFISH_EVENTS_PAGE_ABSDATA = 0x20003 /* (really 0x20000 + EV_ABS) EV_ABS min/max values. */ +}; + +struct goldfish_input_event +{ + uint32_t type; + uint32_t code; + uint32_t value; +}; + +struct goldfish_events_s +{ + FAR void *base; + int irq; + struct work_s work; /* Supports the interrupt handling "bottom half" */ + +#ifdef CONFIG_INPUT_MOUSE + struct mouse_lowerhalf_s mouselower; /* Mouse device lowerhalf instance */ + struct mouse_report_s mousesample; /* Mouse event */ +#endif +#ifdef CONFIG_INPUT_KEYBOARD + struct keyboard_lowerhalf_s keyboardlower; /* Keyboard device lowerhalf instance */ +#endif +#ifdef CONFIG_INPUT_TOUCHSCREEN + struct touch_lowerhalf_s touchlower; /* Touchpad device lowerhalf instance */ + struct touch_sample_s touchsample; /* Touchpad event */ +#endif +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int +goldfish_events_interrupt(int irq, FAR void *dev_id, FAR void *arg); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_INPUT_KEYBOARD + +/**************************************************************************** + * Name: goldfish_events_send_keyboard_event + ****************************************************************************/ + +static bool +goldfish_events_send_keyboard_event(FAR struct goldfish_events_s *events, + FAR struct goldfish_input_event *evt) +{ + if (evt->type == EV_KEY) + { + keyboard_event(&(events->keyboardlower), + keyboard_translate_virtio_code(evt->code), + evt->value); + return true; + } + + return false; +} +#endif + +#ifdef CONFIG_INPUT_MOUSE + +/**************************************************************************** + * Name: goldfish_events_send_mouse_event + ****************************************************************************/ + +static bool +goldfish_events_send_mouse_event(FAR struct goldfish_events_s *events, + FAR struct goldfish_input_event *evt) +{ + if (evt->type == EV_REL) + { + switch (evt->code) + { + case REL_X: + events->mousesample.x = evt->value; + return true; + + case REL_Y: + events->mousesample.y = evt->value; + return true; + + #ifdef CONFIG_INPUT_MOUSE_WHEEL + case REL_WHEEL: + events->mousesample.wheel = evt->value; + return true; + #endif + } + } + else if (evt->type == EV_KEY && evt->value != 0) + { + switch (evt->code) + { + case BTN_LEFT: + events->mousesample.buttons |= MOUSE_BUTTON_1; + return true; + + case BTN_RIGHT: + events->mousesample.buttons |= MOUSE_BUTTON_2; + return true; + + case BTN_MIDDLE: + events->mousesample.buttons |= MOUSE_BUTTON_3; + return true; + } + } + + else if (evt->type == EV_SYN && evt->code == SYN_REPORT && + ((events->mousesample.x != 0) || + (events->mousesample.y != 0) +#ifdef CONFIG_INPUT_MOUSE_WHEEL + || (events->mousesample.wheel != 0) +#endif + )) + { + mouse_event(events->mouselower.priv, &events->mousesample); + memset(&events->mousesample, 0, sizeof(events->mousesample)); + } + + return false; +} +#endif + +#ifdef CONFIG_INPUT_TOUCHSCREEN + +/**************************************************************************** + * Name: goldfish_events_send_touch_event + ****************************************************************************/ + +static bool +goldfish_events_send_touch_event(FAR struct goldfish_events_s *events, + FAR struct goldfish_input_event *evt) +{ + if (evt->type == EV_ABS) + { + switch (evt->code) + { + case ABS_PRESSURE: + events->touchsample.point[0].flags |= TOUCH_PRESSURE_VALID; + events->touchsample.point[0].pressure = evt->value; + return true; + + case ABS_X: + events->touchsample.point[0].flags |= TOUCH_POS_VALID; + events->touchsample.point[0].x = evt->value; + return true; + + case ABS_Y: + events->touchsample.point[0].flags |= TOUCH_POS_VALID; + events->touchsample.point[0].y = evt->value; + return true; + } + } + else if (evt->type == EV_KEY) + { + if (evt->code == BTN_TOUCH) + { + if (evt->value) + { + events->touchsample.point[0].flags |= TOUCH_DOWN; + } + else + { + events->touchsample.point[0].flags |= TOUCH_UP; + } + + return true; + } + } + else if (evt->type == EV_SYN && evt->code == SYN_REPORT && + ((events->touchsample.point[0].pressure != 0) || + (events->touchsample.point[0].x != 0) || + (events->touchsample.point[0].y != 0))) + { + events->touchsample.npoints = 1; + events->touchsample.point[0].timestamp = touch_get_time(); + + touch_event(events->touchlower.priv, &events->touchsample); + memset(&events->touchsample, 0, sizeof(events->touchsample)); + } + + return false; +} +#endif + +/**************************************************************************** + * Name: goldfish_events_worker + ****************************************************************************/ + +static void goldfish_events_worker(FAR void *arg) +{ + FAR struct goldfish_events_s *events = (FAR struct goldfish_events_s *)arg; + struct goldfish_input_event evt; + + evt.type = getreg32(events->base + GOLDFISH_EVENTS_READ); + putreg32(GOLDFISH_EVENTS_PAGE_ABSDATA, + events->base + GOLDFISH_EVENTS_SET_PAGE); + evt.code = getreg32(events->base + GOLDFISH_EVENTS_READ); + putreg32(GOLDFISH_EVENTS_PAGE_ABSDATA, + events->base + GOLDFISH_EVENTS_SET_PAGE); + evt.value = getreg32(events->base + GOLDFISH_EVENTS_READ); + putreg32(GOLDFISH_EVENTS_PAGE_ABSDATA, + events->base + GOLDFISH_EVENTS_SET_PAGE); + + iinfo("goldfish_events_interrupt events(%d,%d,%d).\n", + evt.type, evt.code, evt.value); + +#ifdef CONFIG_INPUT_TOUCHSCREEN + if (goldfish_events_send_touch_event(events, &evt)) + { + goto out; + } +#endif + +#ifdef CONFIG_INPUT_MOUSE + if (goldfish_events_send_mouse_event(events, &evt)) + { + goto out; + } +#endif + +#ifdef CONFIG_INPUT_KEYBOARD + goldfish_events_send_keyboard_event(events, &evt); +#endif + +out: + up_enable_irq(events->irq); +} + +/**************************************************************************** + * Name: goldfish_events_interrupt + ****************************************************************************/ + +static int +goldfish_events_interrupt(int irq, FAR void *dev_id, FAR void *arg) +{ + FAR struct goldfish_events_s *events = arg; + + work_queue(HPWORK, &events->work, goldfish_events_worker, events, 0); + up_disable_irq(events->irq); + + return 0; +} + +/**************************************************************************** + * Name: goldfish_drivers_register + ****************************************************************************/ + +static void goldfish_drivers_register(FAR struct goldfish_events_s *events) +{ +#ifdef CONFIG_INPUT_KEYBOARD + putreg32(GOLDFISH_EVENTS_PAGE_EVBITS | EV_KEY, + events->base + GOLDFISH_EVENTS_SET_PAGE); + if (getreg32(events->base + GOLDFISH_EVENTS_LEN)) + { + putreg32(GOLDFISH_EVENTS_PAGE_ABSDATA, + events->base + GOLDFISH_EVENTS_SET_PAGE); + if (getreg32(events->base + GOLDFISH_EVENTS_LEN)) + { + keyboard_register(&(events->keyboardlower), + "/dev/kbd0", + CONFIG_INPUT_GOLDFISH_NBUFFER); + } + } +#endif + +#ifdef CONFIG_INPUT_MOUSE + putreg32(GOLDFISH_EVENTS_PAGE_EVBITS | EV_REL, + events->base + GOLDFISH_EVENTS_SET_PAGE); + if (getreg32(events->base + GOLDFISH_EVENTS_LEN)) + { + putreg32(GOLDFISH_EVENTS_PAGE_ABSDATA, + events->base + GOLDFISH_EVENTS_SET_PAGE); + if (getreg32(events->base + GOLDFISH_EVENTS_LEN)) + { + mouse_register(&(events->mouselower), + "/dev/mouse0", + CONFIG_INPUT_GOLDFISH_NBUFFER); + } + } +#endif + +#ifdef CONFIG_INPUT_TOUCHSCREEN + putreg32(GOLDFISH_EVENTS_PAGE_EVBITS | EV_ABS, + events->base + GOLDFISH_EVENTS_SET_PAGE); + if (getreg32(events->base + GOLDFISH_EVENTS_LEN)) + { + putreg32(GOLDFISH_EVENTS_PAGE_ABSDATA, + events->base + GOLDFISH_EVENTS_SET_PAGE); + if (getreg32(events->base + GOLDFISH_EVENTS_LEN)) + { + touch_register(&(events->touchlower), + "/dev/touch0", + CONFIG_INPUT_GOLDFISH_NBUFFER); + } + } +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: goldfish_events_register + ****************************************************************************/ + +int goldfish_events_register(FAR void *base, int irq) +{ + FAR struct goldfish_events_s *events; + int ret; + + events = (FAR struct goldfish_events_s *)kmm_zalloc(sizeof(*events)); + if (events == NULL) + { + return -ENOMEM; + } + + events->base = base; + events->irq = irq; + + ret = irq_attach(events->irq, goldfish_events_interrupt, events); + if (ret < 0) + { + goto err_free_events; + } + + /* Register lower half drivers */ + + goldfish_drivers_register(events); + up_enable_irq(events->irq); + + return 0; + +err_free_events: + kmm_free(events); + return ret; +} diff --git a/drivers/input/keyboard_upper.c b/drivers/input/keyboard_upper.c index fb34c9d8f0..cfaf3ed226 100644 --- a/drivers/input/keyboard_upper.c +++ b/drivers/input/keyboard_upper.c @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include #include @@ -419,3 +421,94 @@ void keyboard_event(FAR struct keyboard_lowerhalf_s *lower, uint32_t keycode, nxmutex_unlock(&upper->lock); } + +/**************************************************************************** + * keyboard_translate_virtio_code + ****************************************************************************/ + +uint32_t keyboard_translate_virtio_code(uint16_t keycode) +{ + switch (keycode) + { + case KEY_DELETE: + return KEYCODE_FWDDEL; + case KEY_BACKSPACE: + return KEYCODE_BACKDEL; + case KEY_HOME: + return KEYCODE_HOME; + case KEY_END: + return KEYCODE_END; + case KEY_LEFT: + return KEYCODE_LEFT; + case KEY_RIGHT: + return KEYCODE_RIGHT; + case KEY_UP: + return KEYCODE_UP; + case KEY_DOWN: + return KEYCODE_DOWN; + case KEY_PAGEUP: + return KEYCODE_PAGEUP; + case KEY_PAGEDOWN: + return KEYCODE_PAGEDOWN; + case KEY_ENTER: + return KEYCODE_ENTER; + case KEY_CAPSLOCK: + return KEYCODE_CAPSLOCK; + case KEY_SCROLLLOCK: + return KEYCODE_SCROLLLOCK; + case KEY_NUMLOCK: + return KEYCODE_NUMLOCK; + case KEY_SYSRQ: + return KEYCODE_PRTSCRN; + case KEY_F1: + return KEYCODE_F1; + case KEY_F2: + return KEYCODE_F2; + case KEY_F3: + return KEYCODE_F3; + case KEY_F4: + return KEYCODE_F4; + case KEY_F5: + return KEYCODE_F5; + case KEY_F6: + return KEYCODE_F6; + case KEY_F7: + return KEYCODE_F7; + case KEY_F8: + return KEYCODE_F8; + case KEY_F9: + return KEYCODE_F9; + case KEY_F10: + return KEYCODE_F10; + case KEY_F11: + return KEYCODE_F11; + case KEY_F12: + return KEYCODE_F12; + case KEY_F13: + return KEYCODE_F13; + case KEY_F14: + return KEYCODE_F14; + case KEY_F15: + return KEYCODE_F15; + case KEY_F16: + return KEYCODE_F16; + case KEY_F17: + return KEYCODE_F17; + case KEY_F18: + return KEYCODE_F18; + case KEY_F19: + return KEYCODE_F19; + case KEY_F20: + return KEYCODE_F20; + case KEY_F21: + return KEYCODE_F21; + case KEY_F22: + return KEYCODE_F22; + case KEY_F23: + return KEYCODE_F23; + case KEY_F24: + return KEYCODE_F24; + default: + return keycode; + } +} diff --git a/drivers/virtio/virtio-input.c b/drivers/virtio/virtio-input.c index 605674a8fc..d4f8ef8812 100644 --- a/drivers/virtio/virtio-input.c +++ b/drivers/virtio/virtio-input.c @@ -35,9 +35,9 @@ #include #include #include +#include #include "virtio-input.h" -#include "virtio-input-event-codes.h" /**************************************************************************** * Pre-processor Definitions @@ -106,97 +106,6 @@ static int g_virtio_keyboard_idx = 0; * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: virtio_input_translate_keycode - ****************************************************************************/ - -static uint32_t virtio_input_translate_keycode(uint16_t keycode) -{ - switch (keycode) - { - case KEY_DELETE: - return KEYCODE_FWDDEL; - case KEY_BACKSPACE: - return KEYCODE_BACKDEL; - case KEY_HOME: - return KEYCODE_HOME; - case KEY_END: - return KEYCODE_END; - case KEY_LEFT: - return KEYCODE_LEFT; - case KEY_RIGHT: - return KEYCODE_RIGHT; - case KEY_UP: - return KEYCODE_UP; - case KEY_DOWN: - return KEYCODE_DOWN; - case KEY_PAGEUP: - return KEYCODE_PAGEUP; - case KEY_PAGEDOWN: - return KEYCODE_PAGEDOWN; - case KEY_ENTER: - return KEYCODE_ENTER; - case KEY_CAPSLOCK: - return KEYCODE_CAPSLOCK; - case KEY_SCROLLLOCK: - return KEYCODE_SCROLLLOCK; - case KEY_NUMLOCK: - return KEYCODE_NUMLOCK; - case KEY_SYSRQ: - return KEYCODE_PRTSCRN; - case KEY_F1: - return KEYCODE_F1; - case KEY_F2: - return KEYCODE_F2; - case KEY_F3: - return KEYCODE_F3; - case KEY_F4: - return KEYCODE_F4; - case KEY_F5: - return KEYCODE_F5; - case KEY_F6: - return KEYCODE_F6; - case KEY_F7: - return KEYCODE_F7; - case KEY_F8: - return KEYCODE_F8; - case KEY_F9: - return KEYCODE_F9; - case KEY_F10: - return KEYCODE_F10; - case KEY_F11: - return KEYCODE_F11; - case KEY_F12: - return KEYCODE_F12; - case KEY_F13: - return KEYCODE_F13; - case KEY_F14: - return KEYCODE_F14; - case KEY_F15: - return KEYCODE_F15; - case KEY_F16: - return KEYCODE_F16; - case KEY_F17: - return KEYCODE_F17; - case KEY_F18: - return KEYCODE_F18; - case KEY_F19: - return KEYCODE_F19; - case KEY_F20: - return KEYCODE_F20; - case KEY_F21: - return KEYCODE_F21; - case KEY_F22: - return KEYCODE_F22; - case KEY_F23: - return KEYCODE_F23; - case KEY_F24: - return KEYCODE_F24; - default: - return keycode; - } -} - /**************************************************************************** * Name: virtio_input_send_keyboard_event ****************************************************************************/ @@ -208,7 +117,7 @@ virtio_input_send_keyboard_event(FAR struct virtio_input_priv *priv, if (event->type == EV_KEY) { priv->keyboardsample.code = - virtio_input_translate_keycode(event->code); + keyboard_translate_virtio_code(event->code); priv->keyboardsample.type = event->value; } else if (event->type == EV_SYN && event->code == SYN_REPORT) diff --git a/include/nuttx/input/goldfish_events.h b/include/nuttx/input/goldfish_events.h new file mode 100644 index 0000000000..a62e8cebc6 --- /dev/null +++ b/include/nuttx/input/goldfish_events.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * include/nuttx/input/goldfish_events.h + * + * 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 __INCLUDE_NUTTX_GOLDFISH_EVENTS_H +#define __INCLUDE_NUTTX_GOLDFISH_EVENTS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: goldfish_events_register + * + * Description: + * register goldfish events. + * + * Returned Value: + * None + * + ****************************************************************************/ + +int goldfish_events_register(FAR void *base, int irq); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_GOLDFISH_EVENTS_H */ diff --git a/include/nuttx/input/keyboard.h b/include/nuttx/input/keyboard.h index 27df59d980..6a7e348ab0 100644 --- a/include/nuttx/input/keyboard.h +++ b/include/nuttx/input/keyboard.h @@ -89,6 +89,12 @@ int keyboard_register(FAR struct keyboard_lowerhalf_s *lower, int keyboard_unregister(FAR struct keyboard_lowerhalf_s *lower, FAR const char *path); +/**************************************************************************** + * Name: keyboard_translate_virtio_code + ****************************************************************************/ + +uint32_t keyboard_translate_virtio_code(uint16_t keycode); + #undef EXTERN #ifdef __cplusplus } diff --git a/drivers/virtio/virtio-input-event-codes.h b/include/nuttx/input/virtio-input-event-codes.h similarity index 99% rename from drivers/virtio/virtio-input-event-codes.h rename to include/nuttx/input/virtio-input-event-codes.h index 7bd7ee1649..b8a2aa1f9c 100644 --- a/drivers/virtio/virtio-input-event-codes.h +++ b/include/nuttx/input/virtio-input-event-codes.h @@ -1,5 +1,5 @@ /**************************************************************************** - * drivers/virtio/virtio-input-event-codes.h + * include/nuttx/input/virtio-input-event-codes.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with