mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
drivers/input: add a byte stream mode to the keyboard upper half
The USB HID keyboard driver is about to report through the upper half rather than through a character device of its own, which changes what read() returns from a byte stream to struct keyboard_event_s. Ten in-tree configurations have an application that consumes the byte stream. Add INPUT_KEYBOARD_BYTESTREAM, which renders each event with the keyboard codec instead of copying the event structure, so those applications keep working while they are converted. Only the press events are rendered. A byte stream has no way to say that a key came up, which is exactly what a keyboard reporting through a character device has always delivered, so this reproduces the previous behaviour rather than adding to it. Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
parent
1e93506f84
commit
e00a3a0a2f
2 changed files with 119 additions and 6 deletions
|
|
@ -89,6 +89,25 @@ config INPUT_KEYBOARD
|
|||
bool
|
||||
default n
|
||||
|
||||
config INPUT_KEYBOARD_BYTESTREAM
|
||||
bool "Deliver a byte stream instead of keyboard events"
|
||||
default n
|
||||
depends on INPUT_KEYBOARD && LIBC_KBDCODEC
|
||||
---help---
|
||||
By default a keyboard device delivers struct keyboard_event_s
|
||||
events on read(). Select this to make it deliver the byte stream
|
||||
defined by include/nuttx/input/kbd_codec.h instead, which is what
|
||||
the USB HID keyboard driver provided before it moved to the
|
||||
keyboard upper half.
|
||||
|
||||
This is meant for applications that have not been converted yet.
|
||||
The byte stream cannot express a key release, so an application
|
||||
that needs one has to read the events.
|
||||
|
||||
This applies to every keyboard in the build, so it cannot be used
|
||||
to mix a byte stream consumer and an event consumer in the same
|
||||
configuration.
|
||||
|
||||
config INPUT_UINPUT
|
||||
bool
|
||||
default n
|
||||
|
|
@ -723,7 +742,7 @@ config INPUT_SPQ10KBD
|
|||
select I2C
|
||||
---help---
|
||||
Enable the Solder Party Q10 BlackBerry Keyboard support. This
|
||||
exposes itself as a standard keyboard at /dev/keypadN.
|
||||
exposes itself as a standard keyboard at /dev/kbdN.
|
||||
This keyboard exists both as a standalone module and integrated
|
||||
into the Solder Party Keyboard FeatherWing. Information on this
|
||||
can be found at https://www.solder.party/docs/keyboard-pmod/
|
||||
|
|
@ -783,9 +802,12 @@ config INPUT_KMATRIX_DEBOUNCE
|
|||
|
||||
config INPUT_KMATRIX_DEVPATH
|
||||
string "Device path"
|
||||
default "/dev/keypad0"
|
||||
default "/dev/kbd0"
|
||||
---help---
|
||||
Path where the keyboard matrix device will be registered. Default: /dev/keypad0
|
||||
Path where the keyboard matrix device will be registered. This is
|
||||
the name that applications expect a keyboard to have, so keep the
|
||||
/dev/kbdN form unless the board has a reason to differ.
|
||||
Default: /dev/kbd0
|
||||
|
||||
config INPUT_KMATRIX_I2C
|
||||
bool "Keyboard Matrix via I2C GPIO Expander"
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <nuttx/input/keyboard.h>
|
||||
#include <nuttx/input/kbd_codec.h>
|
||||
#include <nuttx/streams.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/list.h>
|
||||
#include <nuttx/circbuf.h>
|
||||
|
|
@ -42,6 +43,16 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_INPUT_KEYBOARD_BYTESTREAM
|
||||
|
||||
/* The longest sequence that one event can produce in the byte stream. A
|
||||
* normal key is a single byte; a special key is the four byte escape
|
||||
* sequence emitted by kbd_specpress().
|
||||
*/
|
||||
|
||||
# define KEYBOARD_BYTESTREAM_MAX 4
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
|
@ -384,6 +395,66 @@ int keyboard_unregister(FAR struct keyboard_lowerhalf_s *lower,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: keyboard_encode
|
||||
*
|
||||
* Description:
|
||||
* Render one keyboard event as the byte stream that the keyboard codec
|
||||
* defines, for applications that consume characters rather than events.
|
||||
*
|
||||
* Only the press events are rendered. A byte stream has no way to say
|
||||
* that a key came up: a normal key contributes its character and nothing
|
||||
* more, which is what a keyboard reporting through a character device has
|
||||
* always delivered. An application that needs key releases has to read
|
||||
* the events instead.
|
||||
*
|
||||
* Input Parameters:
|
||||
* stream - Memory stream to render into
|
||||
* buf - Buffer of KEYBOARD_BYTESTREAM_MAX bytes backing the stream
|
||||
* keycode - The key
|
||||
* type - The event type
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of bytes rendered, zero if this event has no representation
|
||||
* in the byte stream.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_INPUT_KEYBOARD_BYTESTREAM
|
||||
static size_t keyboard_encode(FAR struct lib_memoutstream_s *stream,
|
||||
FAR char *buf, uint32_t keycode, uint32_t type)
|
||||
{
|
||||
lib_memoutstream(stream, buf, KEYBOARD_BYTESTREAM_MAX);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case KEYBOARD_PRESS:
|
||||
kbd_press(keycode, &stream->common);
|
||||
break;
|
||||
|
||||
case KEYBOARD_SPECPRESS:
|
||||
|
||||
/* Out of range keycodes would trip an assertion in the codec. A
|
||||
* lower half that reports something the codec does not know about
|
||||
* simply does not appear in the byte stream.
|
||||
*/
|
||||
|
||||
if (keycode < FIRST_KEYCODE || keycode > LAST_KEYCODE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
kbd_specpress(keycode, &stream->common);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stream->common.nput;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* keyboard_event
|
||||
****************************************************************************/
|
||||
|
|
@ -393,22 +464,42 @@ void keyboard_event(FAR struct keyboard_lowerhalf_s *lower, uint32_t keycode,
|
|||
{
|
||||
FAR struct keyboard_upperhalf_s *upper = lower->priv;
|
||||
FAR struct keyboard_opriv_s *opriv;
|
||||
struct keyboard_event_s key;
|
||||
int semcount;
|
||||
|
||||
#ifdef CONFIG_INPUT_KEYBOARD_BYTESTREAM
|
||||
struct lib_memoutstream_s stream;
|
||||
char buf[KEYBOARD_BYTESTREAM_MAX];
|
||||
size_t buflen;
|
||||
|
||||
buflen = keyboard_encode(&stream, buf, keycode, type);
|
||||
if (buflen == 0)
|
||||
{
|
||||
/* This event has no representation in the byte stream */
|
||||
|
||||
return;
|
||||
}
|
||||
#else
|
||||
struct keyboard_event_s key;
|
||||
|
||||
key.code = keycode;
|
||||
key.type = type;
|
||||
#endif
|
||||
|
||||
if (nxmutex_lock(&upper->lock) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
key.code = keycode;
|
||||
key.type = type;
|
||||
list_for_every_entry(&upper->head, opriv, struct keyboard_opriv_s, node)
|
||||
{
|
||||
if (nxmutex_lock(&opriv->lock) == 0)
|
||||
{
|
||||
#ifdef CONFIG_INPUT_KEYBOARD_BYTESTREAM
|
||||
circbuf_overwrite(&opriv->circ, buf, buflen);
|
||||
#else
|
||||
circbuf_overwrite(&opriv->circ, &key,
|
||||
sizeof(struct keyboard_event_s));
|
||||
#endif
|
||||
nxsem_get_value(&opriv->waitsem, &semcount);
|
||||
if (semcount < 1)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue