summaryrefslogtreecommitdiff
path: root/NxWidgets/nxwm
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-07-30 17:01:51 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-07-30 17:01:51 -0600
commitd2844edf44290bceada76c5dc0092987a59c18bc (patch)
treea615f09788f294e36b8aa7ed84ed2bf39c2d6ef5 /NxWidgets/nxwm
parent4a9bf5ea04ed5a843e2b029cc65a1d11d19f4bf4 (diff)
downloadnuttx-d2844edf44290bceada76c5dc0092987a59c18bc.tar.gz
nuttx-d2844edf44290bceada76c5dc0092987a59c18bc.tar.bz2
nuttx-d2844edf44290bceada76c5dc0092987a59c18bc.zip
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.
Diffstat (limited to 'NxWidgets/nxwm')
-rw-r--r--NxWidgets/nxwm/include/ckeyboard.hxx50
-rw-r--r--NxWidgets/nxwm/src/ckeyboard.cxx221
-rw-r--r--NxWidgets/nxwm/src/cnxconsole.cxx7
3 files changed, 238 insertions, 40 deletions
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