1
0
Fork 0
forked from nuttx/nuttx-update

Implement encoding the usbhost HID keyboard driver; configre olimex-lpc1766stk HID keyboard configuration to use the kconfig-frontends tool

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5461 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-12-26 18:54:59 +00:00
parent 4cc97f2930
commit 9c8152f308
11 changed files with 1129 additions and 582 deletions

View file

@ -3821,3 +3821,9 @@
* libc/misc/lib_kbdencode.c and lib_kbddecode.c: Add logic to marshal
and serialized "out-of-band" keyboard commands intermixed with normal
ASCII data (not yet hooked into anything).
* drivers/usbhost/usbhost_hidkbd.c: If CONFIG_HIDKBD_ENCODED is
defined, this driver will now use libc/misc/lib_kbdencode.c to
encode special function keys.
* configs/olimex-lpc1766stk/hidkbd: This configuration has been
converted to use the kconfig-frontends configuration tool.

View file

@ -131,7 +131,8 @@
<a href="#pwmdrivers">6.3.12 PWM Drivers</a><br>
<a href="#candrivers">6.3.13 CAN Drivers</a><br>
<a href="#quadencoder">6.3.14 Quadrature Encoder Drivers</a><br>
<a href="#wdogdriver">6.3.15 Watchdog Timer Drivers</a>
<a href="#wdogdriver">6.3.15 Watchdog Timer Drivers</a><br>
<a href="#kbddriver">6.3.16 Keyboard/Keypad Drivers</a><br>
</ul>
<a href="#pwrmgmt">6.4 Power Management</a>
<ul>
@ -3620,6 +3621,151 @@ extern void up_ledoff(int led);
</li>
</ul>
<h3><a name="kbddriver">6.3.16 Keyboard/Keypad Drivers</a></h3>
<p>
<b>&quot;Out-of-Band&quot; Commands</b>.
Keyboards and keypads are the same device for NuttX.
A keypad is thought of as simply a keyboard with fewer keys.
In NuttX, a keyboard/keypad driver is simply a character driver that may have an (optional) encoding/decoding layer on the data returned by the character driver.
A keyboard may return simple text data (alphabetic, numeric, and punctuaction) or control characters (enter, control-C, etc.).
We can think about this the normal &quot;in-band&quot; keyboard data stream.
However, in addition, most keyboards support actions that cannot be represented as text data.
Such actions include things like cursor controls (home, up arrow, page down, etc.), editing functions (insert, delete, etc.), volume controls, (mute, volume up, etc.) and other special functions.
We can think about this as special, &quot;out-of-band&quot; keyboard commands.
In this case, some special encoding may be required to multiplex the in-band text data and out-of-band command streams.
</p>
<p>
<b>Encoding/Decoding</b> Layer</b>.
An optional encoding/decoding layer can be used with the basic character driver to encode the out-of-band commands into the text data stream.
The function interfaces that comprise that encoding/decoding layer are defined in the header file <code>include/nuttx/input/kbd_code.h</code>.
These functions provide an matched set of (a) driver encoding interfaces, and (b) application decoding interfaces.
</p>
<ol>
<li>
<p>
<b>Driver Encoding Interfaces</b>.
</p>
<ul>
<li>
<p>
<b><code>kbd_puttext()</code></b>
</p>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt;nuttx/streams.h&gt;
#include &lt;nuttx/input/kbd_codec.h&gt;
void kbd_puttext(int ch, FAR struct lib_outstream_s *stream);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Put one byte of normal, &quot;in-band&quot; ASCII data into the output stream.
</ul>
<p><b>Input Pameters:</b></p>
<ul>
<li>
<code>ch</code>: The character to be added to the output stream.
</li>
<li>
<code>stream</code>: An instance of <code>lib_outstream_s</code> to perform the actual low-level put operation.
</li>
</ul>
<p><b>Returned Value:</b></p>
<ul>
None.
</ul>
</li>
<li>
<p>
<b><code>kbd_putspecial()</code></b>
</p>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt;nuttx/streams.h&gt;
#include &lt;nuttx/input/kbd_codec.h&gt;
void kbd_putspecial(enum kbd_keycode_e keycode, FAR struct lib_outstream_s *stream);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Put one special, &quot;out-of-band&quot; command into the output stream.
</ul>
<p><b>Input Pameters:</b></p>
<ul>
<li>
<code>keycode</code>: The command to be added to the output stream.
The enumeration <code>enum kbd_keycode_e keycode</code> identifies all commands known to the system.
</li>
<li>
<code>stream</code>: An instance of <code>lib_outstream_s</code> to perform the actual low-level put operation.
</li>
</ul>
<p><b>Returned Value:</b></p>
<ul>
None.
</ul>
</li>
</ul>
</li>
<li>
<p>
<b>Application Decoding Interfaces</b>.
</p>
<ul>
<li>
<p>
<b><code>kbd_get()</code></b>
</p>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt;nuttx/streams.h&gt;
#include &lt;nuttx/input/kbd_codec.h&gt;
int kbd_get(FAR struct lib_instream_s *stream, FAR struct kbd_getstate_s *state, FAR uint8_t *pch);
</pre></ul>
<p><b>Description:</b></p>
<ul>
Get one byte of data or special command from the driver provided input buffer.
</ul>
<p><b>Input Pameters:</b></p>
<ul>
<li>
<code>stream</code>: An instance of <code>lib_instream_s</code> to perform the actual low-level get operation.
</li>
<li>
<code>pch</code>: The location character to save the returned value.
This may be either a normal, &quot;in-band&quot; ASCII characer or a special, "out-of-band" command (i.e., a value from <code>enum kbd_getstate_s</code>.
</li>
<li>
<code>state</code>: A user provided buffer to support parsing.
This structure should be cleared the first time that <code>kbd_get</code> is called.
</li>
</ul>
<p><b>Returned Value:</b></p>
<ul>
<li>
<b>1</b>:
Indicates the successful receipt of a special, &quot;out-of-band&quot; command.
The returned value in <code>pch</code> is a value from <code>enum kbd_getstate_s</code>.
</li>
<li>
<b>0</b>:
Indicates the successful receipt of normal, &quot;in-band&quot; ASCII data.
The returned value in <code>pch</code> is a simple byte of text or control data.
</li>
<li>
<b><code>EOF</code></b>:
An error has getting the next character (reported by the <code>stream</code>).
Normally indicates the end of file.
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>
<b>I/O Streams</b>.
Notice the use of the abstract I/O streams in these interfaces.
These stream interfaces are defined in <code>include/nuttx/streams.h</code>.
</p>
<h2><a name="pwrmgmt">6.4 Power Management</a></h2>
<h3><a name="pmoverview">6.4.1 Overview</a></h3>

View file

@ -899,7 +899,25 @@ Where <subdir> is one of the following:
This configuration directory, performs a simple test of the USB host
HID keyboard class driver using the test logic in apps/examples/hidkbd.
nettest:
NOTES:
1. This configuration uses the mconf-based configuration tool. To
change this configuration using that tool, you should:
a. Build and install the mconf tool. See nuttx/README.txt and
misc/tools/
b. Execute 'make menuconfig' in nuttx/ in order to start the
reconfiguration process.
2. Default platform/toolchain: This is how the build is configured by
be default. These options can easily be re-confured, however.
CONFIG_HOST_WINDOWS=y : Windows
CONFIG_WINDOWS_CYGWIN=y : Cygwin environment on Windows
CONFIG_STM32_CODESOURCERYW=y : CodeSourcery under Windows
nettest:
This configuration directory may be used to enable networking using the
LPC17xx's Ethernet controller. It uses apps/examples/nettest to excercise the
TCP/IP network.

View file

@ -1,39 +0,0 @@
############################################################################
# configs/olimex-lpc1766stk/hidkbd/appconfig
#
# Copyright (C) 2011 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
# Path to example in apps/examples containing the user_start entry point
CONFIGURED_APPS += examples/hidkbd

File diff suppressed because it is too large Load diff

View file

@ -50,7 +50,7 @@ fi
# This is the Cygwin path to the location where I installed the CodeSourcery
# toolchain under windows. You will also have to edit this if you install
# the CodeSourcery toolchain in any other location
# export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery G++ Lite/bin"
export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery G++ Lite/bin"
# These are the Cygwin paths to the locations where I installed the Atollic
# toolchain under windows. You will also have to edit this if you install
@ -62,7 +62,7 @@ fi
# This is the Cygwin path to the location where I build the buildroot
# toolchain.
export TOOLCHAIN_BIN="${WD}/../misc/buildroot/build_arm_nofpu/staging_dir/bin"
# export TOOLCHAIN_BIN="${WD}/../misc/buildroot/build_arm_nofpu/staging_dir/bin"
# The Olimex-lpc1766stk/tools directory
export LPCTOOL_DIR="${WD}/configs/olimex-lpc1766stk/tools"

View file

@ -2,6 +2,7 @@
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
config USBHOST_NPREALLOC
int "Number of pre-allocated class instances"
default 4
@ -29,64 +30,85 @@ config USBHOST_ISOC_DISABLE
On some architectures, selecting this setting will reduce driver size
by disabling isochronous endpoint support
config USBHOST_HIDKBD
bool "HID keyboad class support"
config USBHOST_MSC
bool "Mass Storage Class Support"
default n
depends on !USBHOST_INT_DISABLE && SCHED_WORKQUEUE && !DISABLE_SIGNALS
depends on !BULK_DISABLE
---help---
Enable support for the keyboard class driver. This also depends on
NFILE_DESCRIPTORS > 0 && SCHED_WORKQUEUE=y
config USBHOST_HIDKBD
bool "HID Keyboard Class Support"
default n
depends on !INT_DISABLE
---help---
Enable support for the keyboard class driver. This also depends on
SCHED_WORKQUEUE && !DISABLE_SIGNALS
if USBHOST_HIDKBD
config HIDKBD_POLLUSEC
bool ""
default n
int "Keyboard Poll Rate (MSEC)"
default 100000
---help---
Device poll rate in microseconds. Default: 100 milliseconds.
Device poll rate in microseconds. Default: 100,000 microseconds.
config HIDKBD_DEFPRIO
bool ""
default n
int "Polling Thread Priority"
default 50
---help---
Priority of the polling thread. Default: 50.
config HIDKBD_STACKSIZE
bool ""
default n
int "Polling thread stack size"
default 1024
---help---
Stack size for polling thread. Default: 1024
config HIDKBD_BUFSIZE
bool ""
default n
int "Scancode Buffer Size"
default 64
---help---
Scancode buffer size. Default: 64.
config HIDKBD_NPOLLWAITERS
bool ""
default n
int "Max Number of Waiters for Poll Event"
default 2
depends on !DISABLE_POLL
---help---
If the poll() method is enabled, this defines the maximum number
of threads that can be waiting for keyboard events. Default: 2.
config HIDKBD_RAWSCANCODES
bool ""
bool "Use Raw Scan Codes"
default n
---help---
If set to y no conversion will be made on the raw keyboard scan
codes. Default: ASCII conversion.
If set to y no conversions will be made on the raw keyboard scan
codes. This option is useful during testing. Default: ASCII conversion.
config HIDKBD_ENCODED
bool "Enocode Special Keys"
default n
depends on !HIDKBD_RAWSCANCODES
---help---
Encode special key press events in the user buffer. In this case,
the use end must decode the encoded special key values using the
interfaces defined in include/nuttx/input/kbd_codec.h. These
special keys include such things as up/down arrows, home and end
keys, etc. If this not defined, only 7-bit print-able and control
ASCII characters will be provided to the user.
config HIDKBD_ALLSCANCODES
bool ""
bool "Use All Scancodes"
default n
---help---
If set to y all 231 possible scancodes will be converted to
something. Default: 104 key US keyboard.
config HIDKBD_NODEBOUNCE
bool ""
bool "Disable Debounce"
default n
---help---
If set to y normal debouncing is disabled. Default:
Debounce enabled (No repeat keys).
USB host mass storage class driver. Requires USBHOST=y,
config USBHOST_BULK_DISABLE=n, NFILE_DESCRIPTORS > 0,
and SCHED_WORKQUEUE=y
endif

View file

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/usbhost/usbhost_hidkbd.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -62,6 +62,11 @@
#include <nuttx/usb/usbhost.h>
#include <nuttx/usb/hid.h>
#ifdef CONFIG_HIDKBD_ENCODED
# include <nuttx/streams.h>
# include <nuttx/input/kbd_codec.h>
#endif
/* Don't compile if prerequisites are not met */
#if defined(CONFIG_USBHOST) && !defined(CONFIG_USBHOST_INT_DISABLE) && CONFIG_NFILE_DESCRIPTORS > 0
@ -126,6 +131,14 @@
# endif
#endif
/* If we are using raw scancodes, then we cannot support encoding of
* special characters either.
*/
#ifdef CONFIG_HIDKBD_RAWSCANCODES
# undef CONFIG_HIDKBD_ENCODED
#endif
/* Driver support ***********************************************************/
/* This format is used to construct the /dev/kbd[n] device driver path. It
* defined here so that it will be used consistently in all places.
@ -144,6 +157,23 @@
#define USBHOST_MAX_CREFS 0x7fff
/* Debug ********************************************************************/
/* Both CONFIG_DEBUG_INPUT and CONFIG_DEBUG_USB could apply to this file.
* We assume here that CONFIG_DEBUG_INPUT might be enabled separately, but
* CONFIG_DEBUG_USB implies both.
*/
#ifndef CONFIG_DEBUG_INPUT
# undef idbg
# define idbg udbg
# undef illdbg
# define illdbg ulldbg
# undef ivdbg
# define ivdbg uvdbg
# undef illvdbg
# define illvdbg ullvdbg
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -209,6 +239,16 @@ struct usbhost_state_s
uint8_t kbdbuffer[CONFIG_HIDKBD_BUFSIZE];
};
/* This type is used for encoding special characters */
#ifdef CONFIG_HIDKBD_ENCODED
struct usbhost_outstream_s
{
struct lib_outstream_s stream;
FAR struct usbhost_state_s *priv;
};
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@ -240,7 +280,15 @@ static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *dev
/* Keyboard polling thread */
static void usbhost_destroy(FAR void *arg);
static void usbhost_putbuffer(FAR struct usbhost_state_s *priv, uint8_t keycode);
#ifdef CONFIG_HIDKBD_ENCODED
static void usbhost_putstream(FAR struct lib_outstream_s *this, int ch);
#endif
static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier);
#ifdef CONFIG_HIDKBD_ENCODED
static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
uint8_t scancode, uint8_t modifier);
#endif
static int usbhost_kbdpoll(int argc, char *argv[]);
/* Helpers for usbhost_connect() */
@ -346,6 +394,121 @@ static struct usbhost_state_s *g_priv; /* Data passed to thread */
*/
#ifndef CONFIG_HIDKBD_RAWSCANCODES
#ifdef CONFIG_HIDKBD_ENCODED
/* The first and last scancode values with encode-able values */
#define FIRST_ENCODING USBHID_KBDUSE_ENTER /* 0x28 Keyboard Return (ENTER) */
#ifdef CONFIG_HIDKBD_ALLSCANCODES
# define LAST_ENCODING USBHID_KBDUSE_POWER /* 0x66 Keyboard Power */
#else
#define LAST_ENCODING USBHID_KBDUSE_KPDHEXADECIMAL /* 0xdd Keypad Hexadecimal */
#endif
#define USBHID_NUMENCODINGS (LAST_ENCODING - FIRST_ENCODING + 1)
static const uint8_t encoding[USBHID_NUMENCODINGS] =
{
/* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
KEYCODE_ENTER, 0, KEYCODE_FWDDEL, KEYCODE_BACKDEL, 0, 0, 0, 0,
/* 0x30-0x37: },|,Non-US tilde,:,",grave tidle,<,> */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
0, KEYCODE_CAPSLOCK, KEYCODE_F1, KEYCODE_F2, KEYCODE_F3, KEYCODE_F4, KEYCODE_F5, KEYCODE_F6,
/* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
KEYCODE_F7, KEYCODE_F8, KEYCODE_F9, KEYCODE_F10, KEYCODE_F11, KEYCODE_F12, KEYCODE_PRTSCRN, KEYCODE_SCROLLLOCK,
/* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
KEYCODE_PAUSE, KEYCODE_INSERT, KEYCODE_HOME, KEYCODE_PAGEUP, KEYCODE_FWDDEL, KEYCODE_END, KEYCODE_PAGEDOWN, KEYCODE_RIGHT,
/* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
KEYCODE_LEFT, KEYCODE_DOWN, KEYCODE_UP, KEYCODE_NUMLOCK, 0, 0, 0, 0,
/* 0x58-0x5f: Enter,1-7 */
KEYCODE_ENTER, 0, 0, 0, 0, 0, 0, 0,
/* 0x60-0x66: 8-9,0,.,Non-US \,Application,Power */
0, 0, 0, 0, 0, 0, KEYCODE_POWER,
#ifdef CONFIG_HIDKBD_ALLSCANCODES
0, /* 0x67 = */
/* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
KEYCODE_F13, KEYCODE_F14, KEYCODE_F15, KEYCODE_F16, KEYCODE_F17, KEYCODE_F18, KEYCODE_F19, KEYCODE_F20,
/* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */
KEYCODE_F21, KEYCODE_F22, KEYCODE_F23, KEYCODE_F24, KEYCODE_EXECUTE, KEYCODE_HELP, KEYCODE_MENU, KEYCODE_SELECT,
/* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */
KEYCODE_STOP, KEYCODE_AGAIN, KEYCODE_UNDO, KEYCODE_CUT, KEYCODE_COPY, KEYCODE_PASTE, KEYCODE_FIND, KEYCODE_MUTE,
/* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
KEYCODE_VOLUP, KEYCODE_VOLDOWN, KEYCODE_LCAPSLOCK, KEYCODE_LNUMLOCK, KEYCODE_LSCROLLLOCK, 0, 0, 0,
/* 0x88-0x8f: International 2-9 */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0x90-0x97: LAN 1-8 */
KEYCODE_LANG1, KEYCODE_LANG2, KEYCODE_LANG3, KEYCODE_LANG4, KEYCODE_LANG5, KEYCODE_LANG6, KEYCODE_LANG7, KEYCODE_LANG8,
/* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, KEYCODE_SYSREQ, KEYCODE_CANCEL, KEYCODE_CLEAR, 0, KEYCODE_ENTER, 0,
/* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xa8-0xaf: (reserved) */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xb8-0xbf: {,},tab,backspace,A-D */
0, 0, 0, KEYCODE_BACKDEL, 0, 0, 0, 0,
/* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc8-0xcf: &&,|,||,:,#, ,@,! */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */
KEYCODE_MEMSTORE, KEYCODE_MEMRECALL, KEYCODE_MEMCLEAR, KEYCODE_MEMADD, KEYCODE_MEMSUB, KEYCODE_MEMMUL, KEYCODE_MEMDIV, KEYCODE_NEGATE,
/* 0xd8-0xdd: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */
KEYCODE_CLEAR, KEYCODE_CLEARENTRY, KEYCODE_BINARY, KEYCODE_OCTAL, KEYCODE_DECIMAL, KEYCODE_HEXADECIMAL
#endif
};
#endif
static const uint8_t ucmap[USBHID_NUMSCANCODES] =
{
0, 0, 0, 0, 'A', 'B', 'C', 'D', /* 0x00-0x07: Reserved, errors, A-D */
@ -356,7 +519,7 @@ static const uint8_t ucmap[USBHID_NUMSCANCODES] =
'\n', '\033', '\177', 0, ' ', '_', '+', '{', /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
'}', '|', 0, ':', '"', 0, '<', '>', /* 0x30-0x37: },|,Non-US tilde,:,",grave tidle,<,> */
'?', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,sScrollLock */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
'\n', '1', '2', '3', '4', '4', '6', '7', /* 0x58-0x5f: Enter,1-7 */
@ -368,7 +531,7 @@ static const uint8_t ucmap[USBHID_NUMSCANCODES] =
0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
@ -403,7 +566,7 @@ static const uint8_t lcmap[USBHID_NUMSCANCODES] =
0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
@ -637,6 +800,88 @@ static void usbhost_destroy(FAR void *arg)
usbhost_freeclass(priv);
}
/****************************************************************************
* Name: usbhost_putbuffer
*
* Description:
* Add one character to the user buffer.
*
* Input Parameters:
* priv - Driver internal state
* keycode - The value to add to the user buffer
*
* Returned Values:
* None
*
****************************************************************************/
static void usbhost_putbuffer(FAR struct usbhost_state_s *priv,
uint8_t keycode)
{
register unsigned int head;
register unsigned int tail;
/* Copy the next keyboard character into the user buffer. */
head = priv->headndx;
priv->kbdbuffer[head] = keycode;
/* Increment the head index */
if (++head >= CONFIG_HIDKBD_BUFSIZE)
{
head = 0;
}
/* If the buffer is full, then increment the tail index to make space. Is
* it better to lose old keystrokes or new?
*/
tail = priv->tailndx;
if (tail == head)
{
if (++tail >= CONFIG_HIDKBD_BUFSIZE)
{
tail = 0;
}
/* Save the updated tail index */
priv->tailndx = tail;
}
/* Save the updated head index */
priv->headndx = head;
}
/****************************************************************************
* Name: usbhost_putstream
*
* Description:
* A wrapper for usbhost_putc that is compatibile with the lib_outstream_s
* putc methos.
*
* Input Parameters:
* stream - The struct lib_outstream_s reference
* ch - The character to add to the user buffer
*
* Returned Values:
* None
*
****************************************************************************/
#ifdef CONFIG_HIDKBD_ENCODED
static void usbhost_putstream(FAR struct lib_outstream_s *stream, int ch)
{
FAR struct usbhost_outstream_s *privstream = (FAR struct lib_outstream_s *)stream;
DEBUGASSERT(privstream && privstream->priv);
usbhost_putbuffer(privstream->priv), (uint8_t)ch);
stream->nput++;
}
#endif
/****************************************************************************
* Name: usbhost_mapscancode
*
@ -679,6 +924,58 @@ static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier)
#endif
}
/****************************************************************************
* Name: usbhost_encodescancode
*
* Description:
* Check if the key has a special function encoding and, if it does, add
* the encoded value to the user buffer.
*
* Input Parameters:
* priv - Driver internal state
* scancode - Scan code to be mapped.
* modifier - Ctrl,Alt,Shift,GUI modifier bits
*
* Returned Values:
* None
*
****************************************************************************/
#ifdef CONFIG_HIDKBD_ENCODED
static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
uint8_t scancode, uint8_t modifier)
{
struct usbhost_outstream_s stream;
uint8_t encoded;
/* Check if the raw scancode is in a valid range */
if (scancode >= FIRST_ENCODING && scancode <= LAST_ENCODING)
{
/* Yes the value is within range */
encoded = encoding(scancode - FIRST_ENCODING);
ivdbg(" scancode: %02x modifier: %02x encoded: %d\n",
scancode, modifier, encoded);
if (encoded)
{
struct usbhost_outstream_s usbstream;
/* And it does correspond to a special function key */
usbstream->stream.put = usbhost_putstream;
usbstream->stream.nput = 0;
usbstream->priv = priv;
/* Add the special function value to the user buffer */
kbd_putspecial((enum kbd_keycode_e)encoded, &usbstream);
}
}
}
#endif
/****************************************************************************
* Name: usbhost_kbdpoll
*
@ -704,6 +1001,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
unsigned int npolls = 0;
#endif
unsigned int nerrors = 0;
bool empty = true;
bool newstate;
int ret;
uvdbg("Started\n");
@ -717,13 +1016,13 @@ static int usbhost_kbdpoll(int argc, char *argv[])
* running.
*/
priv = g_priv;
DEBUGASSERT(priv != NULL);
priv = g_priv;
DEBUGASSERT(priv != NULL);
priv->polling = true;
priv->crefs++;
usbhost_givesem(&g_syncsem);
sleep(1);
priv->polling = true;
priv->crefs++;
usbhost_givesem(&g_syncsem);
sleep(1);
/* Loop here until the device is disconnected */
@ -784,17 +1083,12 @@ static int usbhost_kbdpoll(int argc, char *argv[])
else if (priv->open)
{
struct usbhid_kbdreport_s *rpt = (struct usbhid_kbdreport_s *)priv->tbuffer;
unsigned int head;
unsigned int tail;
uint8_t ascii;
uint8_t keycode;
int i;
/* Add the newly received keystrokes to our internal buffer */
usbhost_takesem(&priv->exclsem);
head = priv->headndx;
tail = priv->tailndx;
for (i = 0; i < 6; i++)
{
/* Is this key pressed? But not pressed last time?
@ -828,15 +1122,15 @@ static int usbhost_kbdpoll(int argc, char *argv[])
* or cursor controls in this version of the driver.
*/
ascii = usbhost_mapscancode(rpt->key[i], rpt->modifier);
uvdbg("Key %d: %02x ASCII:%c modifier: %02x\n",
i, rpt->key[i], ascii ? ascii : ' ', rpt->modifier);
keycode = usbhost_mapscancode(rpt->key[i], rpt->modifier);
ivdbg("Key %d: %02x keycode:%c modifier: %02x\n",
i, rpt->key[i], keycode ? keycode : ' ', rpt->modifier);
/* Zero at this point means that the key does not map to a
* printable character.
*/
if (ascii != 0)
if (keycode != 0)
{
/* Handle control characters. Zero after this means
* a valid, NUL character.
@ -844,36 +1138,28 @@ static int usbhost_kbdpoll(int argc, char *argv[])
if ((rpt->modifier & (USBHID_MODIFER_LCTRL|USBHID_MODIFER_RCTRL)) != 0)
{
ascii &= 0x1f;
keycode &= 0x1f;
}
/* Copy the next keyboard character into the user
* buffer.
*/
priv->kbdbuffer[head] = ascii;
/* Increment the head index */
if (++head >= CONFIG_HIDKBD_BUFSIZE)
{
head = 0;
}
/* If the buffer is full, then increment the tail
* index to make space. Is it better to lose old
* keystrokes or new?
*/
if (tail == head)
{
if (++tail >= CONFIG_HIDKBD_BUFSIZE)
{
tail = 0;
}
}
usbhost_putbuffer(priv, keycode);
}
/* The zero might, however, map to a special keyboard action (such as a
* cursor movement or function key). Attempt to encode the special key.
*/
#ifdef CONFIG_HIDKBD_ENCODED
else
{
usbhost_encodescancode(priv, rpt->key[i], rpt->modifier));
}
#endif
}
/* Save the scancode (or lack thereof) for key debouncing on
* next keyboard report.
*/
@ -885,7 +1171,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
/* Did we just transition from no data available to data available? */
if (head != tail && priv->headndx == priv->tailndx)
newstate = (priv->headndx == priv->tailndx);
if (empty && !newstate)
{
/* Yes.. Is there a thread waiting for keyboard data now? */
@ -902,10 +1189,7 @@ static int usbhost_kbdpoll(int argc, char *argv[])
usbhost_pollnotify(priv);
}
/* Update the head/tail indices */
priv->headndx = head;
priv->tailndx = tail;
empty = newstate;
usbhost_givesem(&priv->exclsem);
}
@ -958,6 +1242,7 @@ static int usbhost_kbdpoll(int argc, char *argv[])
usbhost_givesem(&priv->exclsem);
}
return 0;
}

View file

@ -113,7 +113,7 @@ enum kbd_keycode_e
KEYCODE_PAUSE, /* Pause */
KEYCODE_BREAK, /* Break */
KEYCODE_CANCEL, /* Cancel */
KEYCODE_PRINTSCN, /* PrintScreen */
KEYCODE_PRTSCRN, /* PrintScreen */
KEYCODE_SYSREQ, /* SysReq/Attention */
/* Audio */
@ -131,14 +131,15 @@ enum kbd_keycode_e
KEYCODE_CLEAR, /* Clear */
KEYCODE_CLEARENTRY, /* Clear entry */
KEYCODE_NEGATE, /* +/- */
KEYCODE_MEMSET, /* Memory set */
KEYCODE_MEMSTORE, /* Memory store */
KEYCODE_MEMCLEAR, /* Memory clear */
KEYCODE_MEMRECALL, /* Memory recall */
KEYCODE_MEMADD, /* Memory add */
KEYCODE_MEMSUBTRACT, /* Memory substract */
KEYCODE_MEMMULTIPY, /* Memory multiply */
KEYCODE_MEMDIVIDE, /* Memory divide */
KEYCODE_MEMSUB, /* Memory substract */
KEYCODE_MEMMUL, /* Memory multiply */
KEYCODE_MEMDIV, /* Memory divide */
KEYCODE_BINARY, /* Binary mode */
KEYCODE_OCTAL, /* Octal mode */
@ -197,7 +198,7 @@ enum kbd_keycode_e
* Public Types
****************************************************************************/
struct kget_getstate_s
struct kbd_getstate_s
{
uint8_t nch; /* Number of characters in the buffer */
uint8_t ndx; /* Index to next character in the buffer */
@ -225,7 +226,7 @@ extern "C"
* Put one byte of normal, "in-band" ASCII data into the output stream.
*
* Input Parameters:
* ch - The character to be into the output stream.
* ch - The character to be added to the output stream.
* stream - An instance of lib_outstream_s to do the low-level put
* operation.
*
@ -243,6 +244,9 @@ extern "C"
* Put one special, "out-of-band" command into the output stream.
*
* Input Parameters:
* keycode - The command to be added to the output stream.
* stream - An instance of lib_outstream_s to do the low-level put
* operation.
*
* Returned Value:
* None
@ -261,7 +265,7 @@ void kbd_putspecial(enum kbd_keycode_e keycode,
* Name: kbd_get
*
* Description:
* Put one byte of data or special command from the driver provided input
* Get one byte of data or special command from the driver provided input
* buffer.
*
* Input Parameters:
@ -274,15 +278,17 @@ void kbd_putspecial(enum kbd_keycode_e keycode,
* should be cleared the first time that kbd_get is called.
*
* Returned Value:
* 1 - Indicates the successful receipt of a special, "out-of-band" command
* 1 - Indicates the successful receipt of a special, "out-of-band" command.
* The returned value in pch is a value from enum kbd_getstate_s.
* 0 - Indicates the successful receipt of normal, "in-band" ASCII data.
* The returned value in pch is a simple byte of text or control data.
* EOF - An error has getting the next character (reported by the stream).
* Normally indicates the end of file.
*
****************************************************************************/
int kbd_get(FAR struct lib_instream_s *stream,
FAR struct kget_getstate_s *state, FAR uint8_t *pch);
FAR struct kbd_getstate_s *state, FAR uint8_t *pch);
#ifdef __cplusplus
}

View file

@ -89,7 +89,7 @@
*
****************************************************************************/
static int kbd_reget(FAR struct kget_getstate_s *state, FAR uint8_t *pch)
static int kbd_reget(FAR struct kbd_getstate_s *state, FAR uint8_t *pch)
{
/* Return the next character */
@ -107,7 +107,7 @@ static int kbd_reget(FAR struct kget_getstate_s *state, FAR uint8_t *pch)
* Name: kbd_get
*
* Description:
* Put one byte of data or special command from the driver provided input
* Get one byte of data or special command from the driver provided input
* buffer.
*
* Input Parameters:
@ -120,15 +120,17 @@ static int kbd_reget(FAR struct kget_getstate_s *state, FAR uint8_t *pch)
* should be cleared the first time that kbd_get is called.
*
* Returned Value:
* 1 - Indicates the successful receipt of a special, "out-of-band" command
* 1 - Indicates the successful receipt of a special, "out-of-band" command.
* The returned value in pch is a value from enum kbd_getstate_s.
* 0 - Indicates the successful receipt of normal, "in-band" ASCII data.
* The returned value in pch is a simple byte of text or control data.
* EOF - An error has getting the next character (reported by the stream).
* Normally indicates the end of file.
*
****************************************************************************/
int kbd_get(FAR struct lib_instream_s *stream,
FAR struct kget_getstate_s *state, FAR uint8_t *pch)
FAR struct kbd_getstate_s *state, FAR uint8_t *pch)
{
int ch;

View file

@ -62,6 +62,9 @@
* Put one special, "out-of-band" command into the output stream.
*
* Input Parameters:
* keycode - The command to be added to the output stream.
* stream - An instance of lib_outstream_s to do the low-level put
* operation.
*
* Returned Value:
* None