summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NxWidgets/Kconfig23
-rw-r--r--NxWidgets/nxwm/include/ckeyboard.hxx50
-rw-r--r--NxWidgets/nxwm/src/ckeyboard.cxx221
-rw-r--r--NxWidgets/nxwm/src/cnxconsole.cxx7
-rw-r--r--apps/NxWidgets/Kconfig23
-rw-r--r--apps/nshlib/nsh_usbkeyboard.c2
-rw-r--r--nuttx/configs/sama5d4-ek/README.txt31
7 files changed, 287 insertions, 70 deletions
diff --git a/NxWidgets/Kconfig b/NxWidgets/Kconfig
index 52aa90da1..3ee3bd123 100644
--- a/NxWidgets/Kconfig
+++ b/NxWidgets/Kconfig
@@ -855,13 +855,24 @@ config NXWM_KEYBOARD_DEVPATH
string "Keyboard Device Path"
default "/dev/console"
---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
int "Keyboard Task Signal Number"
default 6
---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
config NXWM_KEYBOARD_BUFSIZE
@@ -874,10 +885,10 @@ config NXWM_KEYBOARD_LISTENERPRIO
int "Keyboard Listener Task Priority"
default 120
---help---
- Priority of the touchscreen listener thread.This listener should
- have a higher priority than most display-related tsks otherwise it
- may miss touchscreen events (not really very likely because keyboard
- input is relatively slow). Default: 120
+ Priority of the keyboard listener thread. This listener should
+ have a higher priority than most display-related tasks otherwise it
+ may miss keyboard input (not really very likely because keyboard
+ input is relatively slow). Default: 120
config NXWM_KEYBOARD_LISTENERSTACK
int "Keyboard Listener Task Stack Size"
diff --git a/NxWidgets/nxwm/include/ckeyboard.hxx b/NxWidgets/nxwm/include/ckeyboard.hxx
index 7036472fb..e224fd11c 100644
--- a/NxWidgets/nxwm/include/ckeyboard.hxx
+++ b/NxWidgets/nxwm/include/ckeyboard.hxx
@@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,8 @@
*
****************************************************************************/
-#ifndef __INCLUDE_CKEYBOARD_HXX
-#define __INCLUDE_CKEYBOARD_HXX
+#ifndef __NXWM_INCLUDE_CKEYBOARD_HXX
+#define __NXWM_INCLUDE_CKEYBOARD_HXX
/****************************************************************************
* Included Files
@@ -93,8 +93,46 @@ namespace NxWM
sem_t m_waitSem; /**< Used to synchronize with the listener thread */
/**
- * The keyboard listener thread. This is the entry point of a thread that
- * listeners for and dispatches keyboard events to the NX server.
+ * Open the keyboard device. Not very interesting for the case of
+ * 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*.
* @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
diff --git a/NxWidgets/nxwm/src/ckeyboard.cxx b/NxWidgets/nxwm/src/ckeyboard.cxx
index 0f3f11d37..f643fbf6b 100644
--- a/NxWidgets/nxwm/src/ckeyboard.cxx
+++ b/NxWidgets/nxwm/src/ckeyboard.cxx
@@ -156,60 +156,132 @@ bool CKeyboard::start(void)
return m_state == LISTENER_RUNNING;
}
- /**
- * The keyboard listener thread. This is the entry point of a thread that
- * listeners for and dispatches keyboard events to the NX server.
+/**
+ * Open the keyboard device. Not very interesting for the case of
+ * 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.
*
- * @param arg. The CKeyboard 'this' pointer cast to a void*.
- * @return This function normally does not return but may return NULL on
- * error conditions.
+ * 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.
*/
-FAR void *CKeyboard::listener(FAR void *arg)
+int CKeyboard::open(void)
{
- CKeyboard *This = (CKeyboard *)arg;
+ int fd;
- gvdbg("Listener started\n");
+ // Loop until we have successfully opened the USB keyboard (or until some
+ // irrecoverable error occurs).
- // Open the keyboard device
-
- This->m_kbdFd = std::open(CONFIG_NXWM_KEYBOARD_DEVPATH, O_RDONLY);
- if (This->m_kbdFd < 0)
+ do
{
- 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;
+ // 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);
- // Indicate that we have successfully initialized
+ return fd;
+}
- This->m_state = LISTENER_RUNNING;
- sem_post(&This->m_waitSem);
+/**
+ * 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.
+ */
- // Now loop, reading and dispatching keyboard data
+int CKeyboard::session(void)
+{
+ gvdbg("Session started\n");
- while (This->m_state == LISTENER_RUNNING)
+ // 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(This->m_kbdFd, rxbuffer, CONFIG_NXWM_KEYBOARD_BUFSIZE);
+ ssize_t nbytes = read(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;
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
- gdbg("ERROR: read %s failed: %d\n", CONFIG_NXWM_KEYBOARD_DEVPATH, errval);
- DEBUGASSERT(errval == EINTR);
-#endif
+ // 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
@@ -219,20 +291,103 @@ FAR void *CKeyboard::listener(FAR void *arg)
// Looks like good keyboard input... process it.
// First, get the server handle
- NXHANDLE handle = This->m_server->getServer();
+ 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\n");
+ 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*.
+ * @return This function normally does not return but may return NULL on
+ * error conditions.
+ */
+
+FAR void *CKeyboard::listener(FAR void *arg)
+{
+ CKeyboard *This = (CKeyboard *)arg;
+
+ gvdbg("Listener started\n");
+
+#ifdef CONFIG_NXWM_KEYBOARD_USBHOST
+ // Indicate that we have successfully started. We might be stuck waiting
+ // for a USB keyboard to be connected, but we are technically running
+
+ This->m_state = LISTENER_RUNNING;
+ sem_post(&This->m_waitSem);
+
+ // Loop until we are told to quit
+
+ while (This->m_state == LISTENER_RUNNING)
+#endif
+ {
+ // Open/Re-open the keyboard device
+
+ This->m_kbdFd = This->open();
+ if (This->m_kbdFd < 0)
+ {
+ gdbg("ERROR: open failed: %d\n", This->m_kbdFd);
+ This->m_state = LISTENER_FAILED;
+ sem_post(&This->m_waitSem);
+ return (FAR void *)0;
+ }
+
+#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
- // m_state = LISTENER_STOPREQUESTED
+ // m_state = LISTENER_STOPREQUESTED (or perhaps if some irrecoverable
+ // error has occurred).
gvdbg("Listener exiting\n");
This->m_state = LISTENER_TERMINATED;
diff --git a/NxWidgets/nxwm/src/cnxconsole.cxx b/NxWidgets/nxwm/src/cnxconsole.cxx
index e78e91631..d9bab9cfd 100644
--- a/NxWidgets/nxwm/src/cnxconsole.cxx
+++ b/NxWidgets/nxwm/src/cnxconsole.cxx
@@ -1,7 +1,7 @@
/********************************************************************************************
* 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>
*
* Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,11 @@
/********************************************************************************************
* 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
diff --git a/apps/NxWidgets/Kconfig b/apps/NxWidgets/Kconfig
index 52aa90da1..3ee3bd123 100644
--- a/apps/NxWidgets/Kconfig
+++ b/apps/NxWidgets/Kconfig
@@ -855,13 +855,24 @@ config NXWM_KEYBOARD_DEVPATH
string "Keyboard Device Path"
default "/dev/console"
---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
int "Keyboard Task Signal Number"
default 6
---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
config NXWM_KEYBOARD_BUFSIZE
@@ -874,10 +885,10 @@ config NXWM_KEYBOARD_LISTENERPRIO
int "Keyboard Listener Task Priority"
default 120
---help---
- Priority of the touchscreen listener thread.This listener should
- have a higher priority than most display-related tsks otherwise it
- may miss touchscreen events (not really very likely because keyboard
- input is relatively slow). Default: 120
+ Priority of the keyboard listener thread. This listener should
+ have a higher priority than most display-related tasks otherwise it
+ may miss keyboard input (not really very likely because keyboard
+ input is relatively slow). Default: 120
config NXWM_KEYBOARD_LISTENERSTACK
int "Keyboard Listener Task Stack Size"
diff --git a/apps/nshlib/nsh_usbkeyboard.c b/apps/nshlib/nsh_usbkeyboard.c
index 9baf78955..91aeaaa9a 100644
--- a/apps/nshlib/nsh_usbkeyboard.c
+++ b/apps/nshlib/nsh_usbkeyboard.c
@@ -116,7 +116,7 @@ static int nsh_wait_usbready(FAR const char *msg)
/* ENOENT means that the USB device is not yet connected and,
* hence, has no entry under /dev. If the USB driver still
- * exists under(because other threads still have the driver
+ * exists under /dev (because other threads still have the driver
* open), then we might also get ENODEV. Anything else would
* be really bad.
*/
diff --git a/nuttx/configs/sama5d4-ek/README.txt b/nuttx/configs/sama5d4-ek/README.txt
index 46a64433a..4a14fd1fd 100644
--- a/nuttx/configs/sama5d4-ek/README.txt
+++ b/nuttx/configs/sama5d4-ek/README.txt
@@ -4060,30 +4060,27 @@ Configurations
recognized.
The USB keyboard is configured to replace the NSH stdin device some
- that NSH will take input from the USB keyboard. These are the
- relevant configuration options:
+ that NSH will take input from the USB keyboard. This has to be
+ done a little differently for the case of NxWM::CNxConsoles than
+ in the standard NSH configuration. Here the relevant configuration
+ options are:
- CONFIG_NSH_USBKBD=y
- CONFIG_NSH_USBKBD_DEVNAME="/dev/kbda"
-
- When NSH comes up, it will attempt to open /dev/kbda and replace
- stdin with that device. If no USB keyboard is connected when you
- start the NxConsole, you will see:
+ CONFIG_NXWM_KEYBOARD_USBHOST=y
+ CONFIG_NXWM_KEYBOARD_DEVPATH="/dev/kbda"
- Waiting for a keyboard...
-
- NSH will then automatically start when the keyboard is attached:
+ NSH will then automatically start when the NxConsole is started:
NuttShell (NSH) NuttX-7.3
nsh>
- If the keyboard is detached, NSH will stop and wait for you to
- re-attach the keyboard:
-
- nsh> nsh: nsh_session: readline failed: 1
- Please re-connect the keyboard...
+ When the NxConsole comes up, it will attempt to use /dev/kbda device
+ for input. Obviously, you cannot enter text if there is no keyboard
+ but otherwise you will not see any indication whether a keyboard is
+ connected or not.
- And the session will restart when the keyboard is reconnected.
+ If the keyboard is detached, you not be able to enter text until the
+ keyboard is reconnected. Again, there is no other special indication
+ of the keyboard state.
The keyboard is currently configured to poll at 80 MSec intervals.
That might not be fast enough for you if you are a fast typist. This