Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Documentation/applications/examples/hidkbd/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
80 changes: 49 additions & 31 deletions Documentation/applications/examples/lvglterm/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
====
Expand All @@ -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.

Expand Down
99 changes: 99 additions & 0 deletions Documentation/applications/system/kbd/index.rst
Original file line number Diff line number Diff line change
@@ -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 [<device>] [<count>]
kbd -i <device> [<source>]

Without ``-i`` it reads ``<device>`` and prints what arrives, stopping
after ``<count>`` 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.
Original file line number Diff line number Diff line change
Expand Up @@ -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
----

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading