NSH Keyboard: Close stdin before trying to reopen. Otherwise, driver will persist

This commit is contained in:
Gregory Nutt 2014-07-03 17:08:59 -06:00
parent c40b48ce55
commit 14297d4e30

View File

@ -92,6 +92,16 @@ static int nsh_wait_usbready(FAR const char *msg)
* not be available until the device is connected to the host and enumerated. * not be available until the device is connected to the host and enumerated.
*/ */
/* Close standard fd 0. Unbeknownst to stdin. We do this here in case we
* had the USB keyboard device open. In that case, the driver will exist
* we will get an ENODEV error when we try to open it (instead of ENOENT).
*
* NOTE: This might not be portable behavior!
*/
(void)close(0);
sleep(1);
/* Open the USB keyboard device for read-only access */ /* Open the USB keyboard device for read-only access */
do do
@ -101,11 +111,18 @@ static int nsh_wait_usbready(FAR const char *msg)
fd = open(NSH_USBKBD_DEVNAME, O_RDONLY); fd = open(NSH_USBKBD_DEVNAME, O_RDONLY);
if (fd < 0) if (fd < 0)
{ {
#ifdef CONFIG_DEBUG
int errcode = errno;
/* ENOENT means that the USB device is not yet connected and, /* ENOENT means that the USB device is not yet connected and,
* hence, has no entry under /dev. Anything else would be bad. * hence, has no entry under /dev. If the USB driver still
* exists under(because other threads still have the driver
* open), then we might also get ENODEV. Anything else would
* be really bad.
*/ */
DEBUGASSERT(errno == ENOENT); DEBUGASSERT(errcode == ENOENT || errcode == ENODEV);
#endif
/* Let the user know that we are waiting */ /* Let the user know that we are waiting */
@ -127,21 +144,21 @@ static int nsh_wait_usbready(FAR const char *msg)
} }
while (fd < 0); while (fd < 0);
/* Okay.. we have successfully opened a keyboard device /* Okay.. we have successfully opened a keyboard device. Did
* * we just re-open fd 0?
* Close standard fd 0. Unbeknownst to stdin.
* NOTE: This might not be portable behavior!
*/ */
(void)close(0); if (fd != 0)
{
/* Dup the fd to create standard fd 0. stdin should not know */ /* No.. Dup the fd to create standard fd 0. stdin should not know. */
(void)dup2(fd, 0); (void)dup2(fd, 0);
/* Close the keyboard device that we just opened */ /* Close the keyboard device that we just opened */
close(fd); close(fd);
}
return OK; return OK;
} }
@ -195,7 +212,7 @@ int nsh_consolemain(int argc, char *argv[])
/* Now loop, executing creating a session for each USB connection */ /* Now loop, executing creating a session for each USB connection */
msg = "Waiting for keyboard to be connected...\n"; msg = "Waiting for a keyboard...\n";
for (;;) for (;;)
{ {
/* Wait for the USB to be connected to the host and switch /* Wait for the USB to be connected to the host and switch
@ -204,8 +221,8 @@ int nsh_consolemain(int argc, char *argv[])
ret = nsh_wait_usbready(msg); ret = nsh_wait_usbready(msg);
(void)ret; /* Eliminate warning if not used */
DEBUGASSERT(ret == OK); DEBUGASSERT(ret == OK);
UNUSED(ret);
/* Execute the session */ /* Execute the session */