dd support for a USB keyboard as the NxConsole and text widget input. Not fully functional as of this initial check-in. Basic functionality is there, but there are conditions were the keyboard gets lost.
This commit is contained in:
parent
a4656341df
commit
aa42efa31b
23
Kconfig
23
Kconfig
@ -855,13 +855,24 @@ config NXWM_KEYBOARD_DEVPATH
|
|||||||
string "Keyboard Device Path"
|
string "Keyboard Device Path"
|
||||||
default "/dev/console"
|
default "/dev/console"
|
||||||
---help---
|
---help---
|
||||||
The full path to the touchscreen device. Default: "/dev/console"
|
The full path to the keyboard device. Default: "/dev/console"
|
||||||
|
|
||||||
|
config NXWM_KEYBOARD_USBHOST
|
||||||
|
bool "USB Keyboard Device"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
This setting indicates that NXWM_KEYBOARD_DEVPATH is a USB keyboard.
|
||||||
|
A USB Keyboard is a removable device. When it is inserted, then
|
||||||
|
device at NXWM_KEYBOARD_DEVPATH will appear; when it removed,
|
||||||
|
keyboard reads will fail and the device at NXWM_KEYBOARD_DEVPATH
|
||||||
|
will disappear. Selecting this option builds addtional logic into
|
||||||
|
the keyboard listener thread in order to handle this case.
|
||||||
|
|
||||||
config NXWM_KEYBOARD_SIGNO
|
config NXWM_KEYBOARD_SIGNO
|
||||||
int "Keyboard Task Signal Number"
|
int "Keyboard Task Signal Number"
|
||||||
default 6
|
default 6
|
||||||
---help---
|
---help---
|
||||||
The realtime signal used to wake up the touchscreen listener thread.
|
The realtime signal used to wake up the keyboard listener thread.
|
||||||
Default: 6
|
Default: 6
|
||||||
|
|
||||||
config NXWM_KEYBOARD_BUFSIZE
|
config NXWM_KEYBOARD_BUFSIZE
|
||||||
@ -874,10 +885,10 @@ config NXWM_KEYBOARD_LISTENERPRIO
|
|||||||
int "Keyboard Listener Task Priority"
|
int "Keyboard Listener Task Priority"
|
||||||
default 120
|
default 120
|
||||||
---help---
|
---help---
|
||||||
Priority of the touchscreen listener thread.This listener should
|
Priority of the keyboard listener thread. This listener should
|
||||||
have a higher priority than most display-related tsks otherwise it
|
have a higher priority than most display-related tasks otherwise it
|
||||||
may miss touchscreen events (not really very likely because keyboard
|
may miss keyboard input (not really very likely because keyboard
|
||||||
input is relatively slow). Default: 120
|
input is relatively slow). Default: 120
|
||||||
|
|
||||||
config NXWM_KEYBOARD_LISTENERSTACK
|
config NXWM_KEYBOARD_LISTENERSTACK
|
||||||
int "Keyboard Listener Task Stack Size"
|
int "Keyboard Listener Task Stack Size"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* NxWidgets/nxwm/include/keyboard.hxx
|
* NxWidgets/nxwm/include/keyboard.hxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -33,8 +33,8 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef __INCLUDE_CKEYBOARD_HXX
|
#ifndef __NXWM_INCLUDE_CKEYBOARD_HXX
|
||||||
#define __INCLUDE_CKEYBOARD_HXX
|
#define __NXWM_INCLUDE_CKEYBOARD_HXX
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
@ -93,8 +93,46 @@ namespace NxWM
|
|||||||
sem_t m_waitSem; /**< Used to synchronize with the listener thread */
|
sem_t m_waitSem; /**< Used to synchronize with the listener thread */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The keyboard listener thread. This is the entry point of a thread that
|
* Open the keyboard device. Not very interesting for the case of
|
||||||
* listeners for and dispatches keyboard events to the NX server.
|
* standard device but much more interesting for a USB keyboard device
|
||||||
|
* that may disappear when the keyboard is disconnect but later reappear
|
||||||
|
* when the keyboard is reconnected. In this case, this function will
|
||||||
|
* not return until the keyboard device was successfully opened (or
|
||||||
|
* until an irrecoverable error occurs.
|
||||||
|
*
|
||||||
|
* Opens the keyboard device specified by CONFIG_NXWM_KEYBOARD_DEVPATH.
|
||||||
|
*
|
||||||
|
* @return On success, then method returns a valid file descriptor that
|
||||||
|
* can be used to redirect stdin. A negated errno value is returned
|
||||||
|
* if an irrecoverable error occurs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline int open(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the heart of the keyboard listener thread. It contains the
|
||||||
|
* actual logic that listeners for and dispatches keyboard events to the
|
||||||
|
* NX server.
|
||||||
|
*
|
||||||
|
* @return If the session terminates gracefully (i.e., because >m_state
|
||||||
|
* is no longer equal to LISTENER_RUNNING, then method returns OK. A
|
||||||
|
* negated errno value is returned if an error occurs while reading from
|
||||||
|
* the keyboard device. A read error, depending upon the type of the
|
||||||
|
* error, may simply indicate that a USB keyboard was removed and we
|
||||||
|
* should wait for the keyboard to be connected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline int session(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The keyboard listener thread. This is the entry point of a thread
|
||||||
|
* that listeners for and dispatches keyboard events to the NX server.
|
||||||
|
* It simply opens the keyboard device (using CKeyboard::open()) and
|
||||||
|
* executes the session (via CKeyboard::session()).
|
||||||
|
*
|
||||||
|
* If an errors while reading from the keyboard device AND we are
|
||||||
|
* configured to use a USB keyboard, then this function will wait for
|
||||||
|
* the USB keyboard to be re-connected.
|
||||||
*
|
*
|
||||||
* @param arg. The CKeyboard 'this' pointer cast to a void*.
|
* @param arg. The CKeyboard 'this' pointer cast to a void*.
|
||||||
* @return This function normally does not return but may return NULL on
|
* @return This function normally does not return but may return NULL on
|
||||||
@ -130,4 +168,4 @@ namespace NxWM
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __INCLUDE_CKEYBOARD_HXX
|
#endif // __NXWM_INCLUDE_CKEYBOARD_HXX
|
||||||
|
@ -156,9 +156,166 @@ bool CKeyboard::start(void)
|
|||||||
return m_state == LISTENER_RUNNING;
|
return m_state == LISTENER_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The keyboard listener thread. This is the entry point of a thread that
|
* Open the keyboard device. Not very interesting for the case of
|
||||||
* listeners for and dispatches keyboard events to the NX server.
|
* standard device but much more interesting for a USB keyboard device
|
||||||
|
* that may disappear when the keyboard is disconnect but later reappear
|
||||||
|
* when the keyboard is reconnected. In this case, this function will
|
||||||
|
* not return until the keyboard device was successfully opened (or
|
||||||
|
* until an irrecoverable error occurs.
|
||||||
|
*
|
||||||
|
* Opens the keyboard device specified by CONFIG_NXWM_KEYBOARD_DEVPATH.
|
||||||
|
*
|
||||||
|
* @return On success, then method returns a valid file descriptor that
|
||||||
|
* can be used to redirect stdin. A negated errno value is returned
|
||||||
|
* if an irrecoverable error occurs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int CKeyboard::open(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
// Loop until we have successfully opened the USB keyboard (or until some
|
||||||
|
// irrecoverable error occurs).
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Try to open the keyboard device
|
||||||
|
|
||||||
|
fd = std::open(CONFIG_NXWM_KEYBOARD_DEVPATH, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
int errcode = errno;
|
||||||
|
DEBUGASSERT(errcode > 0);
|
||||||
|
|
||||||
|
// EINTR should be ignored because it is not really an error at
|
||||||
|
// all. We should retry immediately
|
||||||
|
|
||||||
|
if (errcode != EINTR)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NXWM_KEYBOARD_USBHOST
|
||||||
|
// ENOENT means that the USB device is not yet connected and,
|
||||||
|
// hence, has no entry under /dev. If the USB driver still
|
||||||
|
// exists under /dev (because other threads still have the driver
|
||||||
|
// open), then we might also get ENODEV.
|
||||||
|
|
||||||
|
if (errcode == ENOENT || errcode == ENODEV)
|
||||||
|
{
|
||||||
|
// REVIST: Can we inject a constant string here to let the
|
||||||
|
// user know that we are waiting for a USB keyboard to be
|
||||||
|
// connected?
|
||||||
|
|
||||||
|
// Sleep a bit and try again
|
||||||
|
|
||||||
|
gvdbg("WAITING for a USB device\n");
|
||||||
|
std::sleep(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anything else would be really bad.
|
||||||
|
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// Let the top-level logic decide what it wants to do
|
||||||
|
// about all really bad things
|
||||||
|
|
||||||
|
gdbg("ERROR: Failed to open %s for reading: %d\n",
|
||||||
|
CONFIG_NXWM_KEYBOARD_DEVPATH, errcode);
|
||||||
|
return -errcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (fd < 0);
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the heart of the keyboard listener thread. It contains the
|
||||||
|
* actual logic that listeners for and dispatches keyboard events to the
|
||||||
|
* NX server.
|
||||||
|
*
|
||||||
|
* @return If the session terminates gracefully (i.e., because >m_state
|
||||||
|
* is no longer equal to LISTENER_RUNNING), then method returns OK. A
|
||||||
|
* negated errno value is returned if an error occurs while reading from
|
||||||
|
* the keyboard device. A read error, depending upon the type of the
|
||||||
|
* error, may simply indicate that a USB keyboard was removed and we
|
||||||
|
* should wait for the keyboard to be connected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int CKeyboard::session(void)
|
||||||
|
{
|
||||||
|
gvdbg("Session started\n");
|
||||||
|
|
||||||
|
// Loop, reading and dispatching keyboard data
|
||||||
|
|
||||||
|
while (m_state == LISTENER_RUNNING)
|
||||||
|
{
|
||||||
|
// Read one keyboard sample
|
||||||
|
|
||||||
|
gvdbg("Listening for keyboard input\n");
|
||||||
|
|
||||||
|
uint8_t rxbuffer[CONFIG_NXWM_KEYBOARD_BUFSIZE];
|
||||||
|
ssize_t nbytes = read(m_kbdFd, rxbuffer,
|
||||||
|
CONFIG_NXWM_KEYBOARD_BUFSIZE);
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
|
||||||
|
if (nbytes < 0)
|
||||||
|
{
|
||||||
|
int errcode = errno;
|
||||||
|
DEBUGASSERT(errcode > 0);
|
||||||
|
|
||||||
|
// EINTR is not really an error, it simply means that something is
|
||||||
|
// trying to get our attention. We need to check m_state to see
|
||||||
|
// if we were asked to terminate
|
||||||
|
|
||||||
|
if (errcode != EINTR)
|
||||||
|
{
|
||||||
|
// Let the top-level listener logic decide what to do about
|
||||||
|
// the read failure.
|
||||||
|
|
||||||
|
gdbg("ERROR: read %s failed: %d\n",
|
||||||
|
CONFIG_NXWM_KEYBOARD_DEVPATH, errcode);
|
||||||
|
return -errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdbg("Awakened with EINTR\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give the keyboard input to NX
|
||||||
|
|
||||||
|
else if (nbytes > 0)
|
||||||
|
{
|
||||||
|
// Looks like good keyboard input... process it.
|
||||||
|
// First, get the server handle
|
||||||
|
|
||||||
|
NXHANDLE handle = m_server->getServer();
|
||||||
|
|
||||||
|
// Then inject the keyboard input into NX
|
||||||
|
|
||||||
|
int ret = nx_kbdin(handle, (uint8_t)nbytes, rxbuffer);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
gdbg("ERROR: nx_kbdin failed: %d\n", ret);
|
||||||
|
//break; ignore the error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The keyboard listener thread. This is the entry point of a thread
|
||||||
|
* that listeners for and dispatches keyboard events to the NX server.
|
||||||
|
* It simply opens the keyboard device (using CKeyboard::open()) and
|
||||||
|
* executes the session (via CKeyboard::session()).
|
||||||
|
*
|
||||||
|
* If an errors while reading from the keyboard device AND we are
|
||||||
|
* configured to use a USB keyboard, then this function will wait for
|
||||||
|
* the USB keyboard to be re-connected.
|
||||||
*
|
*
|
||||||
* @param arg. The CKeyboard 'this' pointer cast to a void*.
|
* @param arg. The CKeyboard 'this' pointer cast to a void*.
|
||||||
* @return This function normally does not return but may return NULL on
|
* @return This function normally does not return but may return NULL on
|
||||||
@ -171,68 +328,66 @@ FAR void *CKeyboard::listener(FAR void *arg)
|
|||||||
|
|
||||||
gvdbg("Listener started\n");
|
gvdbg("Listener started\n");
|
||||||
|
|
||||||
// Open the keyboard device
|
#ifdef CONFIG_NXWM_KEYBOARD_USBHOST
|
||||||
|
// Indicate that we have successfully started. We might be stuck waiting
|
||||||
This->m_kbdFd = std::open(CONFIG_NXWM_KEYBOARD_DEVPATH, O_RDONLY);
|
// for a USB keyboard to be connected, but we are technically running
|
||||||
if (This->m_kbdFd < 0)
|
|
||||||
{
|
|
||||||
gdbg("ERROR Failed to open %s for reading: %d\n",
|
|
||||||
CONFIG_NXWM_KEYBOARD_DEVPATH, errno);
|
|
||||||
This->m_state = LISTENER_FAILED;
|
|
||||||
sem_post(&This->m_waitSem);
|
|
||||||
return (FAR void *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indicate that we have successfully initialized
|
|
||||||
|
|
||||||
This->m_state = LISTENER_RUNNING;
|
This->m_state = LISTENER_RUNNING;
|
||||||
sem_post(&This->m_waitSem);
|
sem_post(&This->m_waitSem);
|
||||||
|
|
||||||
// Now loop, reading and dispatching keyboard data
|
// Loop until we are told to quit
|
||||||
|
|
||||||
while (This->m_state == LISTENER_RUNNING)
|
while (This->m_state == LISTENER_RUNNING)
|
||||||
{
|
|
||||||
// Read one keyboard sample
|
|
||||||
|
|
||||||
gvdbg("Listening for keyboard input\n");
|
|
||||||
|
|
||||||
uint8_t rxbuffer[CONFIG_NXWM_KEYBOARD_BUFSIZE];
|
|
||||||
ssize_t nbytes = read(This->m_kbdFd, rxbuffer, CONFIG_NXWM_KEYBOARD_BUFSIZE);
|
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
|
|
||||||
if (nbytes < 0)
|
|
||||||
{
|
|
||||||
// The only expect error is to be interrupt by a signal
|
|
||||||
#ifdef CONFIG_DEBUG
|
|
||||||
int errval = errno;
|
|
||||||
|
|
||||||
gdbg("ERROR: read %s failed: %d\n", CONFIG_NXWM_KEYBOARD_DEVPATH, errval);
|
|
||||||
DEBUGASSERT(errval == EINTR);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
{
|
||||||
|
// Open/Re-open the keyboard device
|
||||||
|
|
||||||
// Give the keyboard input to NX
|
This->m_kbdFd = This->open();
|
||||||
|
if (This->m_kbdFd < 0)
|
||||||
else if (nbytes > 0)
|
|
||||||
{
|
{
|
||||||
// Looks like good keyboard input... process it.
|
gdbg("ERROR: open failed: %d\n", This->m_kbdFd);
|
||||||
// First, get the server handle
|
This->m_state = LISTENER_FAILED;
|
||||||
|
sem_post(&This->m_waitSem);
|
||||||
NXHANDLE handle = This->m_server->getServer();
|
return (FAR void *)0;
|
||||||
|
|
||||||
// Then inject the keyboard input into NX
|
|
||||||
|
|
||||||
int ret = nx_kbdin(handle, (uint8_t)nbytes, rxbuffer);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
gdbg("ERROR: nx_kbdin failed\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_NXWM_KEYBOARD_USBHOST
|
||||||
|
// Indicate that we have successfully initialized
|
||||||
|
|
||||||
|
This->m_state = LISTENER_RUNNING;
|
||||||
|
sem_post(&This->m_waitSem);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Now execute the session. The session will run until either (1) we
|
||||||
|
// were asked to terminate gracefully (with m_state !=LISTENER_RUNNING),
|
||||||
|
// of if an error occurred while reading from the keyboard device. If
|
||||||
|
// we are configured to use a USB keyboard, then this error, depending
|
||||||
|
// upon what the error is, may indicate that the USB keyboard has been
|
||||||
|
// removed. In that case, we need to continue looping and, hopefully,
|
||||||
|
// the USB keyboard will be reconnected.
|
||||||
|
|
||||||
|
int ret = This->session();
|
||||||
|
#ifdef CONFIG_NXWM_KEYBOARD_USBHOST
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: CKeyboard::session() returned %d\n", ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// No errors from session() are expected
|
||||||
|
|
||||||
|
DEBUGASSERT(ret == OK);
|
||||||
|
UNUSED(ret);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Close the keyboard device
|
||||||
|
|
||||||
|
(void)std::close(This->m_kbdFd);
|
||||||
|
This->m_kbdFd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should get here only if we were asked to terminate via
|
// We should get here only if we were asked to terminate via
|
||||||
// m_state = LISTENER_STOPREQUESTED
|
// m_state = LISTENER_STOPREQUESTED (or perhaps if some irrecoverable
|
||||||
|
// error has occurred).
|
||||||
|
|
||||||
gvdbg("Listener exiting\n");
|
gvdbg("Listener exiting\n");
|
||||||
This->m_state = LISTENER_TERMINATED;
|
This->m_state = LISTENER_TERMINATED;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* NxWidgets/nxwm/src/cnxconsole.cxx
|
* NxWidgets/nxwm/src/cnxconsole.cxx
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2012. 2104 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -60,6 +60,11 @@
|
|||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* Pre-Processor Definitions
|
* Pre-Processor Definitions
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
/* Configuration ****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NSH_USBKBD
|
||||||
|
# warning You probably do not really want CONFIG_NSH_USBKBD, try CONFIG_NXWM_KEYBOARD_USBHOST
|
||||||
|
#endif
|
||||||
|
|
||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
|
Loading…
x
Reference in New Issue
Block a user