drivers/input: report special keys from the keyboard matrix

The matrix driver reported every key with KEYBOARD_PRESS and
KEYBOARD_RELEASE, so a board whose matrix has arrows or function keys
had no way to say so:  the keycode ranges overlap the character range,
and the event type is what tells them apart.

A keymap entry is a uint32_t, so wrap the entry in KMATRIX_SPECIAL() to
declare that it holds a value from enum kbd_keycode_e.  Existing keymaps
hold characters and are unaffected.

While here, drop the cast that truncated the keycode to sixteen bits,
and default the device to /dev/kbd0.  Applications look for a keyboard
under that name, and /dev/keypad0 kept the matrix out of reach of every
one of them.

Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
Jorge Guzman 2026-07-30 15:33:33 -03:00 committed by Alan C. Assis
parent f47fd03407
commit 59101fa206
2 changed files with 38 additions and 7 deletions

View file

@ -175,6 +175,7 @@ static void kmatrix_scan_worker(FAR void *arg)
bool pressed;
bool old_state;
uint32_t keycode;
uint32_t type;
int ret;
ret = nxmutex_lock(&priv->lock);
@ -212,13 +213,28 @@ static void kmatrix_scan_worker(FAR void *arg)
kmatrix_set_state(priv, row, col, pressed);
kmatrix_reset_debounce(priv, row, col);
/* Generate keyboard event */
/* Generate keyboard event. A keymap entry wrapped in
* KMATRIX_SPECIAL() is a keycode rather than a character,
* and has to be reported with a SPEC event type: the two
* ranges overlap, so the type is the only way the
* application can tell them apart.
*/
keycode = priv->config->keymap[
row * priv->config->ncols + col];
keyboard_event(&priv->lower, (uint16_t)keycode,
pressed ? KEYBOARD_PRESS :
KEYBOARD_RELEASE);
if ((keycode & KMATRIX_SPECIAL_FLAG) != 0)
{
keycode &= ~KMATRIX_SPECIAL_FLAG;
type = pressed ? KEYBOARD_SPECPRESS :
KEYBOARD_SPECREL;
}
else
{
type = pressed ? KEYBOARD_PRESS : KEYBOARD_RELEASE;
}
keyboard_event(&priv->lower, keycode, type);
iinfo("Key [%d,%d]: %s (code %lu)\n", row, col,
pressed ? "PRESS" : "RELEASE",

View file

@ -35,6 +35,21 @@
* Pre-processor Definitions
****************************************************************************/
/* A keymap entry is normally the character that the key produces. Wrap it
* in KMATRIX_SPECIAL() instead to declare that the entry is a value from
* enum kbd_keycode_e, so that the key is reported as a special key rather
* than as the character that happens to share its value:
*
* static const uint32_t g_keymap[] =
* {
* '1', '2', '3',
* KMATRIX_SPECIAL(KEYCODE_UP), KMATRIX_SPECIAL(KEYCODE_DOWN), '0',
* };
*/
#define KMATRIX_SPECIAL_FLAG (UINT32_C(1) << 31)
#define KMATRIX_SPECIAL(k) ((k) | KMATRIX_SPECIAL_FLAG)
/****************************************************************************
* Public Types
****************************************************************************/
@ -91,12 +106,12 @@ extern "C"
*
* Description:
* Configure and register a keyboard matrix device. This will create the
* /dev/keypadN device node and enable keyboard scanning.
* /dev/kbdN device node and enable keyboard scanning.
*
* Input Parameters:
* config - The keyboard matrix configuration. This structure is not
* copied; it must persist for the lifetime of the driver.
* devpath - The device path for the /dev/keypadN device.
* devpath - The device path for the /dev/kbdN device.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
@ -125,7 +140,7 @@ struct ioexpander_dev_s;
* ioe_dev - IO expander device (from mcp23x08_initialize or
* pca9538_initialize)
* config - The keyboard matrix configuration (with callbacks set)
* devpath - The device path for the /dev/keypadN device
* devpath - The device path for the /dev/kbdN device
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is