From 7a87a7ee07bb163b0bf70350bb0ace7c55fafdb9 Mon Sep 17 00:00:00 2001 From: Jorge Guzman Date: Thu, 30 Jul 2026 17:50:29 -0300 Subject: [PATCH 1/3] boards/arm/stm32h7/linum-stm32h753bi: drive lvglterm from the serial console The terminal reads a keyboard device and does not care which one, so it can be driven with no keyboard plugged in at all. Enable UINPUT_KEYBOARD and system/kbd so that the configuration can do it out of the box, and document how, including how to have the USB keyboard and the console feed the terminal at the same time. The terminal no longer has a USB specific input source either, so the device path has to be spelled out: the USB HID driver names its devices /dev/kbda onwards while the option defaults to /dev/kbd0. INPUT_KEYBOARD_BYTESTREAM is not needed here. The terminal reads events now, and this configuration has no other keyboard consumer. UINPUT_KEYBOARD_BUFNUMBER is raised to 128. It counts events rather than keys, so the default of eight holds four keystrokes, and a console hands over a whole line at once. The upper half overwrites the oldest event when the buffer is full, so a typed line arrived with its beginning silently missing. HIDKBD_NOGETREPORT is enabled as well. Sampling the keyboard over the control pipe every 40 ms loses any key pressed and released between two samples, which on this board meant most of them. Signed-off-by: Jorge Guzman --- .../boards/linum-stm32h753bi/index.rst | 31 +++++++++++++++++++ .../configs/lvglterm_kbda/defconfig | 8 ++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst b/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst index 3e2c85d0d9c7c..65d38f22a9a66 100644 --- a/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst +++ b/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst @@ -1087,6 +1087,37 @@ that the USB host and the SDMMC peripheral coexist:: nsh> mount -t vfat /dev/mmcsd0 /data nsh> ls /data +**Typing from the serial console instead.** The terminal reads a keyboard +device, and it does not care which one, so it can be driven from the serial +console with no keyboard plugged in at all. This configuration enables +``UINPUT_KEYBOARD``, which registers a virtual keyboard on +``/dev/ukeyboard``, and ``system/kbd``, which injects into it. + +Point the terminal at the virtual keyboard and bridge the console into it:: + + nsh> lvglterm /dev/ukeyboard & + nsh> kbd -i /dev/ukeyboard + +Everything typed on the serial console from that point on appears on the +display. This is how to work on the terminal without the keyboard at hand, +and how to reach the board over a serial link from another machine. + +To use both at once, forward the USB keyboard into the same virtual +keyboard before starting the terminal:: + + nsh> kbd -i /dev/ukeyboard /dev/kbda & + nsh> lvglterm /dev/ukeyboard & + nsh> kbd -i /dev/ukeyboard + +The USB keyboard and the serial console now feed the same terminal, which +an application cannot do on its own since it opens a single device. + +``UINPUT_KEYBOARD_BUFNUMBER`` is raised to 128 here. It counts events +rather than keys, so the default of eight holds four keystrokes, and a +console hands over a whole line at once. The keyboard upper half overwrites +the oldest event when the buffer is full, so a line typed at the console +would arrive with its beginning silently missing. + tone ---- diff --git a/boards/arm/stm32h7/linum-stm32h753bi/configs/lvglterm_kbda/defconfig b/boards/arm/stm32h7/linum-stm32h753bi/configs/lvglterm_kbda/defconfig index 490dc686d077d..60c8ff2e28e29 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/configs/lvglterm_kbda/defconfig +++ b/boards/arm/stm32h7/linum-stm32h753bi/configs/lvglterm_kbda/defconfig @@ -30,7 +30,8 @@ CONFIG_DEBUG_FEATURES=y CONFIG_DEBUG_SYMBOLS=y CONFIG_DRIVERS_VIDEO=y CONFIG_EXAMPLES_LVGLTERM=y -CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_USB=y +CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD=y +CONFIG_EXAMPLES_LVGLTERM_KBD_DEV="/dev/kbda" CONFIG_FAT_DMAMEMORY=y CONFIG_FAT_LCNAMES=y CONFIG_FAT_LFN=y @@ -40,6 +41,7 @@ CONFIG_FS_PROCFS=y CONFIG_GRAN=y CONFIG_GRAN_INTR=y CONFIG_GRAPHICS_LVGL=y +CONFIG_HIDKBD_NOGETREPORT=y CONFIG_INIT_ENTRYPOINT="nsh_main" CONFIG_INTELHEX_BINARY=y CONFIG_LIBC_EXECFUNCS=y @@ -81,11 +83,15 @@ CONFIG_STM32_PWR=y CONFIG_STM32_RTC=y CONFIG_STM32_SDMMC1=y CONFIG_STM32_USART1=y +CONFIG_SYSTEM_KBD=y CONFIG_SYSTEM_NSH=y CONFIG_TASK_NAME_SIZE=0 CONFIG_TESTING_RAMTEST=y +CONFIG_UINPUT_KEYBOARD=y +CONFIG_UINPUT_KEYBOARD_BUFNUMBER=128 CONFIG_USART1_SERIAL_CONSOLE=y CONFIG_USBHOST=y +CONFIG_USBHOST_ASYNCH=y CONFIG_USBHOST_HIDKBD=y CONFIG_USEC_PER_TICK=1000 CONFIG_VIDEO_FB=y From d2458583631dc221a455f30cddd0f8f875332f01 Mon Sep 17 00:00:00 2001 From: Jorge Guzman Date: Thu, 30 Jul 2026 18:09:54 -0300 Subject: [PATCH 2/3] Documentation: follow the keyboard change in the application docs The lvglterm page still told the reader to pick the input source that matches the hardware, which was the whole thing being removed: it has one physical keyboard variant now, and reads whatever is registered. The hidkbd page pointed at HIDKBD_ENCODED, which no longer exists. What produces that byte stream now is INPUT_KEYBOARD_BYTESTREAM. system/kbd had no page at all. Signed-off-by: Jorge Guzman --- .../applications/examples/hidkbd/index.rst | 12 ++- .../applications/examples/lvglterm/index.rst | 80 +++++++++------ .../applications/system/kbd/index.rst | 99 +++++++++++++++++++ 3 files changed, 158 insertions(+), 33 deletions(-) create mode 100644 Documentation/applications/system/kbd/index.rst diff --git a/Documentation/applications/examples/hidkbd/index.rst b/Documentation/applications/examples/hidkbd/index.rst index a95266e57be8f..0ffb131bbf4cc 100644 --- a/Documentation/applications/examples/hidkbd/index.rst +++ b/Documentation/applications/examples/hidkbd/index.rst @@ -14,5 +14,13 @@ This is a simple test to ``debug/verify`` the USB host HID keyboard class driver in ``include/nuttx/input/kbd_codec.h`` to decode the returned keyboard data. These special keys include such things as up/down arrows, home and end keys, etc. If this not defined, only 7-bit printable and control ASCII characters - will be provided to the user. Requires ``CONFIG_HIDKBD_ENCODED`` and - ``CONFIG_LIBC_KBDCODEC``. + will be provided to the user. Requires + ``CONFIG_INPUT_KEYBOARD_BYTESTREAM`` and ``CONFIG_LIBC_KBDCODEC``. + +.. note:: + + This example reads the byte stream that the USB HID keyboard driver used + to deliver on its own, which now comes from + ``CONFIG_INPUT_KEYBOARD_BYTESTREAM``. New work should use ``kbd`` + instead: it reads any keyboard, in either format, and reports key + releases as well. diff --git a/Documentation/applications/examples/lvglterm/index.rst b/Documentation/applications/examples/lvglterm/index.rst index 18e93d34b8637..5ca60f2b8e8d2 100644 --- a/Documentation/applications/examples/lvglterm/index.rst +++ b/Documentation/applications/examples/lvglterm/index.rst @@ -4,8 +4,8 @@ LVGL application that runs an interactive NuttShell (NSH) on the display. NSH is started with its standard streams redirected through pipes, its output is -rendered in an LVGL text area, and the input comes from one of three sources -selected at build time. +rendered in an LVGL text area, and the input comes from either a touchscreen +or a keyboard, selected at build time. The shared code lives in ``lvglterm.c`` (NSH startup, output rendering, main loop); ``lvglterm_touch.c`` and ``lvglterm_kbd.c`` implement the input @@ -15,9 +15,7 @@ Input variants ============== The input source is chosen with the *LVGL Terminal input source* Kconfig -choice (only one is built at a time). The physical-keyboard options differ in -the data the keyboard device returns on ``read()``, so the one that matches the -hardware must be selected. +choice (only one is built at a time). On-screen keyboard (touch) ``CONFIG_EXAMPLES_LVGLTERM_INPUT_TOUCH`` (default). An LVGL keyboard @@ -31,39 +29,60 @@ On-screen keyboard (touch) On-screen keyboard (touch) variant -Matrix / upper-half keyboard - ``CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_MATRIX``. ``struct - keyboard_event_s`` events are read from a keyboard registered through the - ``CONFIG_INPUT_KEYBOARD`` upper half (for example the M5Stack Cardputer - matrix keyboard on ``/dev/kbd0``) and streamed to the shell; the output - fills the whole screen. The Fn Up/Down cursor keys scroll the output. +Physical keyboard + ``CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD``. Keys are read from a keyboard + registered with ``keyboard_register()`` and streamed to the shell; the + output fills the whole screen. The Up and Down cursor keys scroll the + output. Any keyboard works, and the terminal does not need to know which + kind it is: USB HID, a matrix, the simulator, virtio. .. figure:: lvglterm-kbd.png :align: center :width: 500px :alt: LVGL Terminal driven by a matrix keyboard - Matrix / upper-half keyboard variant - -USB HID keyboard - ``CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_USB``. A USB HID keyboard (for - example on ``/dev/kbda`` with ``CONFIG_USBHOST_HIDKBD``) delivers a byte - stream that is decoded with the keyboard codec and streamed to the shell. - When the driver is built with ``CONFIG_HIDKBD_ENCODED`` the Up/Down cursor - keys scroll the terminal. + Physical keyboard variant, driven by a matrix keyboard .. figure:: lvglterm-usb.png :align: center :width: 500px :alt: LVGL Terminal driven by a USB HID keyboard - USB HID keyboard variant + The same variant, driven by a USB HID keyboard + +The keyboard defaults to ``CONFIG_EXAMPLES_LVGLTERM_KBD_DEV`` and can be +overridden at run time by passing the path as the first argument +(``lvglterm /dev/kbd1``) when more than one keyboard is present. Note that +the USB HID driver names its devices ``/dev/kbda`` onwards, since they come +and go as keyboards are plugged in, while the option defaults to +``/dev/kbd0``. + +The terminal reads ``struct keyboard_event_s`` events unless the kernel was +built with ``CONFIG_INPUT_KEYBOARD_BYTESTREAM``, in which case it reads the +byte stream that the keyboard codec defines. That is a property of the build +rather than of the hardware, so it is not something to configure here. + +Driving the terminal without a keyboard +--------------------------------------- + +Because the terminal reads a keyboard device and does not care which one, it +can be driven from the serial console with nothing plugged in. Enable +``CONFIG_UINPUT_KEYBOARD``, which registers a virtual keyboard on +``/dev/ukeyboard``, and ``CONFIG_SYSTEM_KBD``, which injects into it:: + + nsh> lvglterm /dev/ukeyboard & + nsh> kbd -i /dev/ukeyboard + +Everything typed on the console appears on the display from that point on. +Forwarding a real keyboard into the same virtual one lets both drive the +terminal at once, which it cannot do by itself since it opens a single +device:: + + nsh> kbd -i /dev/ukeyboard /dev/kbda & -Both keyboard variants default the device to -``CONFIG_EXAMPLES_LVGLTERM_KBD_DEV`` (``/dev/kbd0`` for the matrix keyboard, -``/dev/kbda`` for USB) and can be overridden at run time by passing the path -as the first argument (``lvglterm /dev/kbd1``) when more than one keyboard is -present. +Raise ``CONFIG_UINPUT_KEYBOARD_BUFNUMBER`` when doing this. It counts events +rather than keys, so the default of eight holds four keystrokes, and a +console hands over a whole line at once. Font ==== @@ -81,13 +100,12 @@ Configuration - ``CONFIG_SYSTEM_NSH=y`` -- the NSH library must be enabled. - ``CONFIG_GRAPHICS_LVGL=y`` and ``CONFIG_LV_USE_NUTTX=y`` -- LVGL with its NuttX integration. -- A display (``CONFIG_LV_USE_NUTTX_LCD`` or a framebuffer). Each input variant +- A display (``CONFIG_LV_USE_NUTTX_LCD`` or a framebuffer). Each input variant also needs its own driver: a touchscreen - (``CONFIG_LV_USE_NUTTX_TOUCHSCREEN``) for the touch variant, - ``CONFIG_INPUT_KEYBOARD`` for the matrix variant, or - ``CONFIG_USBHOST_HIDKBD`` for the USB variant. The USB variant selects - ``CONFIG_LIBC_KBDCODEC`` automatically and, for the cursor keys, the driver - should be built with ``CONFIG_HIDKBD_ENCODED``. + (``CONFIG_LV_USE_NUTTX_TOUCHSCREEN``) for the touch variant, or + ``CONFIG_INPUT_KEYBOARD`` and a keyboard driver for the physical variant. + ``CONFIG_LIBC_KBDCODEC`` is selected automatically when the build delivers + the byte stream. - The selected font (``CONFIG_LV_FONT_UNSCII_8`` or ``CONFIG_LV_FONT_UNSCII_16``) is enabled automatically by the font choice. diff --git a/Documentation/applications/system/kbd/index.rst b/Documentation/applications/system/kbd/index.rst new file mode 100644 index 0000000000000..0fd6698081bdb --- /dev/null +++ b/Documentation/applications/system/kbd/index.rst @@ -0,0 +1,99 @@ +=================================== +``kbd`` Keyboard dump and injection +=================================== + +Description +----------- + +The ``kbd`` application prints every event that a keyboard reports. Any +keyboard registered with ``keyboard_register()`` is read the same way, +whatever the hardware behind it is, so this works with a USB HID keyboard, +a matrix, the simulator, virtio or VNC without being told which. + +It is the first thing to run when bringing up a keyboard on a new board: +if the events look right here, every application that reads a keyboard +will see the same thing. + +It replaces the ``hidkbd`` and ``keyboard`` examples, which did this for +one kind of keyboard each and could not read the other. + +Usage +----- + +.. code-block:: bash + + kbd [] [] + kbd -i [] + +Without ``-i`` it reads ```` and prints what arrives, stopping +after ```` keys if one is given. The device defaults to +``CONFIG_SYSTEM_KBD_DEVPATH``. It waits for the device to appear rather +than failing, since a USB keyboard shows up when it is plugged in. + +With ``-i`` it writes instead of reading. See `Injecting keys`_ below. + +Output +------ + +A key that produces a character is reported with the character, and a key +that does not, such as an arrow or a modifier, with a value from +``enum kbd_keycode_e``. The two ranges overlap, so the event type is what +tells them apart:: + + nsh> kbd /dev/kbd0 + kbd: reading /dev/kbd0, keyboard events + press code 97 'a' + release code 97 'a' + specpress keycode 7 + specrel keycode 7 + +The four types are ``press`` and ``release`` for characters, ``specpress`` +and ``specrel`` for keycodes. A driver that reports its arrow keys as +plain presses is not following the contract, and its arrows will be +dropped by applications that do. + +The device delivers ``struct keyboard_event_s`` events unless the kernel +was built with ``CONFIG_INPUT_KEYBOARD_BYTESTREAM``, in which case it +delivers the byte stream that the keyboard codec defines. This follows +that setting rather than having a switch of its own, and says which one it +is on the first line. + +Injecting keys +-------------- + +With ``-i`` the tool goes the other way and writes into a virtual keyboard, +so that an application can be driven with no keyboard hardware at all. +This needs ``CONFIG_UINPUT_KEYBOARD``, which registers ``/dev/ukeyboard``. + +Given no source it injects what it reads from its own stdin, which is the +serial console:: + + nsh> kbd -i /dev/ukeyboard + kbd: injecting into /dev/ukeyboard, type to send, Ctrl-D to stop + +Given a source it forwards every key of one keyboard onto another:: + + nsh> kbd -i /dev/ukeyboard /dev/kbda & + kbd: forwarding /dev/kbda into /dev/ukeyboard + +Point an application at ``/dev/ukeyboard`` and both reach it at once, +which the application cannot do by itself since it opens a single device. + +.. note:: + + Raise ``CONFIG_UINPUT_KEYBOARD_BUFNUMBER`` before injecting. It counts + events rather than keys, so the default of eight holds four keystrokes, + and a console hands over a whole line at once. The keyboard upper half + overwrites the oldest event when the buffer is full, so a typed line + arrives with its beginning missing and nothing says so. + +Configuration +------------- + +- ``CONFIG_SYSTEM_KBD`` enables the application. +- ``CONFIG_SYSTEM_KBD_DEVPATH`` is the keyboard to read when none is named + on the command line. Default ``/dev/kbd0``. Note that the USB HID driver + names its devices ``/dev/kbda`` onwards, since they come and go as + keyboards are plugged in. +- ``CONFIG_SYSTEM_KBD_PROGNAME``, ``CONFIG_SYSTEM_KBD_PRIORITY`` and + ``CONFIG_SYSTEM_KBD_STACKSIZE`` are the usual task settings. From eaae1d90eafaef67e3933dd9da3a155aef266182 Mon Sep 17 00:00:00 2001 From: Jorge Guzman Date: Thu, 30 Jul 2026 19:47:37 -0300 Subject: [PATCH 3/3] boards/xtensa/esp32s3/esp32s3-m5-cardputer: follow the unified lvglterm input The terminal no longer has separate matrix and USB input sources: it reads any keyboard through one path. Left as it was, the unknown symbol would have been dropped and the configuration would have fallen back to the touch variant, which is the default. This board has no touchscreen, so the terminal would have had no input at all and the build would have said nothing. Signed-off-by: Jorge Guzman --- .../esp32s3/esp32s3-m5-cardputer/configs/lvglterm/defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/xtensa/esp32s3/esp32s3-m5-cardputer/configs/lvglterm/defconfig b/boards/xtensa/esp32s3/esp32s3-m5-cardputer/configs/lvglterm/defconfig index 5bb9c031f0986..349e37a7e9521 100644 --- a/boards/xtensa/esp32s3/esp32s3-m5-cardputer/configs/lvglterm/defconfig +++ b/boards/xtensa/esp32s3/esp32s3-m5-cardputer/configs/lvglterm/defconfig @@ -47,7 +47,7 @@ CONFIG_ESP32S3_USBSERIAL=y CONFIG_ESPRESSIF_WIFI=y CONFIG_EXAMPLES_LVGLTERM=y CONFIG_EXAMPLES_LVGLTERM_FONT_UNSCII_8=y -CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD_MATRIX=y +CONFIG_EXAMPLES_LVGLTERM_INPUT_KBD=y CONFIG_FAT_LCNAMES=y CONFIG_FAT_LFN=y CONFIG_FS_FAT=y