mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
system/kbd: add a keyboard dump that reads any keyboard
The hidkbd and keyboard examples do the same thing for one kind of keyboard each: hidkbd reads a USB HID keyboard as a byte stream, and keyboard reads an upper half keyboard as events. Neither works with the other, so bringing up a new keyboard means picking the right example first, and there is no answer for somebody whose keyboard is neither. Every keyboard registered with keyboard_register() is read the same way, so one tool covers them all: USB HID, matrix, simulator, virtio, VNC. The payload follows INPUT_KEYBOARD_BYTESTREAM rather than a switch of its own. An application has no business knowing what hardware is behind the device, and a build cannot mix the two formats anyway. The two examples stay for now. They are what the in-tree configurations still name, and removing them has to wait until those configurations have been moved over. Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
parent
37a1f0e068
commit
ad2242d812
5 changed files with 395 additions and 0 deletions
35
system/kbd/CMakeLists.txt
Normal file
35
system/kbd/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# ##############################################################################
|
||||
# apps/system/kbd/CMakeLists.txt
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
if(CONFIG_SYSTEM_KBD)
|
||||
nuttx_add_application(
|
||||
NAME
|
||||
${CONFIG_SYSTEM_KBD_PROGNAME}
|
||||
PRIORITY
|
||||
${CONFIG_SYSTEM_KBD_PRIORITY}
|
||||
STACKSIZE
|
||||
${CONFIG_SYSTEM_KBD_STACKSIZE}
|
||||
MODULE
|
||||
${CONFIG_SYSTEM_KBD}
|
||||
SRCS
|
||||
kbd_main.c)
|
||||
endif()
|
||||
38
system/kbd/Kconfig
Normal file
38
system/kbd/Kconfig
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config SYSTEM_KBD
|
||||
tristate "Keyboard dump"
|
||||
default n
|
||||
depends on INPUT_KEYBOARD
|
||||
---help---
|
||||
Dump what a keyboard reports. This reads any keyboard registered
|
||||
with keyboard_register(), whatever the hardware behind it is, so it
|
||||
is the tool to reach for when bringing up a new keyboard.
|
||||
|
||||
Replaces the hidkbd and keyboard examples, which did the same thing
|
||||
for one kind of keyboard each.
|
||||
|
||||
if SYSTEM_KBD
|
||||
|
||||
config SYSTEM_KBD_PROGNAME
|
||||
string "Program name"
|
||||
default "kbd"
|
||||
|
||||
config SYSTEM_KBD_PRIORITY
|
||||
int "Task priority"
|
||||
default 100
|
||||
|
||||
config SYSTEM_KBD_STACKSIZE
|
||||
int "Task stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
|
||||
config SYSTEM_KBD_DEVPATH
|
||||
string "Keyboard device path"
|
||||
default "/dev/kbd0"
|
||||
---help---
|
||||
The keyboard to read when none is named on the command line.
|
||||
|
||||
endif
|
||||
25
system/kbd/Make.defs
Normal file
25
system/kbd/Make.defs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
############################################################################
|
||||
# apps/system/kbd/Make.defs
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_SYSTEM_KBD),)
|
||||
CONFIGURED_APPS += $(APPDIR)/system/kbd
|
||||
endif
|
||||
32
system/kbd/Makefile
Normal file
32
system/kbd/Makefile
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
############################################################################
|
||||
# apps/system/kbd/Makefile
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
PROGNAME = $(CONFIG_SYSTEM_KBD_PROGNAME)
|
||||
PRIORITY = $(CONFIG_SYSTEM_KBD_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_SYSTEM_KBD_STACKSIZE)
|
||||
MODULE = $(CONFIG_SYSTEM_KBD)
|
||||
|
||||
MAINSRC = kbd_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
265
system/kbd/kbd_main.c
Normal file
265
system/kbd/kbd_main.c
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/****************************************************************************
|
||||
* apps/system/kbd/kbd_main.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Dump what a keyboard reports.
|
||||
*
|
||||
* Every keyboard registered with keyboard_register() is read the same way,
|
||||
* whatever the hardware behind it is: a USB HID keyboard, a matrix, the
|
||||
* simulator, virtio. So this works with all of them, and it is the place
|
||||
* to look when bringing up a new one.
|
||||
*
|
||||
* The device delivers struct keyboard_event_s events unless the kernel was
|
||||
* built with 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.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <nuttx/input/keyboard.h>
|
||||
|
||||
#ifdef CONFIG_INPUT_KEYBOARD_BYTESTREAM
|
||||
# include <nuttx/streams.h>
|
||||
# include <nuttx/input/kbd_codec.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define KBD_READ_SIZE 64
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kbd_typename
|
||||
****************************************************************************/
|
||||
|
||||
static FAR const char *kbd_typename(uint32_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case KEYBOARD_PRESS:
|
||||
return "press";
|
||||
|
||||
case KEYBOARD_RELEASE:
|
||||
return "release";
|
||||
|
||||
case KEYBOARD_SPECPRESS:
|
||||
return "specpress";
|
||||
|
||||
case KEYBOARD_SPECREL:
|
||||
return "specrel";
|
||||
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kbd_show
|
||||
*
|
||||
* Description:
|
||||
* Print one key. A normal key carries a character, a special key carries
|
||||
* a value from enum kbd_keycode_e, and the type is what says which.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void kbd_show(uint32_t code, uint32_t type)
|
||||
{
|
||||
if (type == KEYBOARD_PRESS || type == KEYBOARD_RELEASE)
|
||||
{
|
||||
printf("%-9s code %3" PRIu32 " '%c'\n", kbd_typename(type), code,
|
||||
isprint(code) ? (int)code : '.');
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%-9s keycode %" PRIu32 "\n", kbd_typename(type), code);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kbd_dump
|
||||
*
|
||||
* Description:
|
||||
* Print everything in one read.
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of keys printed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_INPUT_KEYBOARD_BYTESTREAM
|
||||
static size_t kbd_dump(FAR char *buffer, size_t nbytes)
|
||||
{
|
||||
struct lib_meminstream_s stream;
|
||||
struct kbd_getstate_s state;
|
||||
uint8_t ch;
|
||||
size_t nkeys = 0;
|
||||
int ret;
|
||||
|
||||
lib_meminstream(&stream, buffer, nbytes);
|
||||
memset(&state, 0, sizeof(state));
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
ret = kbd_decode(&stream.common, &state, &ch);
|
||||
if (ret == KBD_ERROR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
kbd_show(ch, ret);
|
||||
nkeys++;
|
||||
}
|
||||
|
||||
return nkeys;
|
||||
}
|
||||
#else
|
||||
static size_t kbd_dump(FAR char *buffer, size_t nbytes)
|
||||
{
|
||||
FAR struct keyboard_event_s *key = (FAR struct keyboard_event_s *)buffer;
|
||||
size_t nkeys = 0;
|
||||
|
||||
if ((nbytes % sizeof(struct keyboard_event_s)) != 0)
|
||||
{
|
||||
fprintf(stderr, "kbd: short read of %zu bytes, ignoring\n", nbytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (nbytes >= sizeof(struct keyboard_event_s))
|
||||
{
|
||||
kbd_show(key->code, key->type);
|
||||
|
||||
nbytes -= sizeof(struct keyboard_event_s);
|
||||
key++;
|
||||
nkeys++;
|
||||
}
|
||||
|
||||
return nkeys;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: main
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR const char *devpath = CONFIG_SYSTEM_KBD_DEVPATH;
|
||||
char buffer[KBD_READ_SIZE];
|
||||
size_t nkeys = 0;
|
||||
size_t limit = 0;
|
||||
ssize_t nbytes;
|
||||
int fd;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
devpath = argv[1];
|
||||
}
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
limit = strtoul(argv[2], NULL, 10);
|
||||
}
|
||||
|
||||
/* Wait for the device. A USB keyboard appears when it is plugged in, so
|
||||
* this is the normal way to start rather than an error path.
|
||||
*/
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
fd = open(devpath, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
printf("kbd: waiting for %s: %d\n", devpath, errno);
|
||||
fflush(stdout);
|
||||
sleep(3);
|
||||
}
|
||||
|
||||
printf("kbd: reading %s, %s\n", devpath,
|
||||
#ifdef CONFIG_INPUT_KEYBOARD_BYTESTREAM
|
||||
"byte stream"
|
||||
#else
|
||||
"keyboard events"
|
||||
#endif
|
||||
);
|
||||
fflush(stdout);
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
nbytes = read(fd, buffer, sizeof(buffer));
|
||||
if (nbytes < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr, "kbd: read %s failed: %d\n", devpath, errno);
|
||||
break;
|
||||
}
|
||||
else if (nbytes == 0)
|
||||
{
|
||||
/* The keyboard is gone */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
nkeys += kbd_dump(buffer, nbytes);
|
||||
|
||||
if (limit > 0 && nkeys >= limit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
printf("kbd: %zu keys\n", nkeys);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue