diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-07-30 17:01:51 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-07-30 17:01:51 -0600 |
commit | d2844edf44290bceada76c5dc0092987a59c18bc (patch) | |
tree | a615f09788f294e36b8aa7ed84ed2bf39c2d6ef5 /NxWidgets/nxwm | |
parent | 4a9bf5ea04ed5a843e2b029cc65a1d11d19f4bf4 (diff) | |
download | nuttx-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.hxx | 50 | ||||
-rw-r--r-- | NxWidgets/nxwm/src/ckeyboard.cxx | 221 | ||||
-rw-r--r-- | NxWidgets/nxwm/src/cnxconsole.cxx | 7 |
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 |