mirror of
https://github.com/apache/nuttx.git
synced 2026-05-26 02:36:11 +08:00
Fix readline return value; Add support for removable serial devices
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5589 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -4069,4 +4069,8 @@
|
|||||||
this.
|
this.
|
||||||
* arch/arm/src/lm/chip/lm4f_memorymap.h: More LM4F changes from
|
* arch/arm/src/lm/chip/lm4f_memorymap.h: More LM4F changes from
|
||||||
Jose Pablo Carballo.
|
Jose Pablo Carballo.
|
||||||
|
* drivers/serial/serial.c, include/nuttx/serial/serial.h,
|
||||||
|
drivers/usbdev/cdcacm.c, and drivers/pl2303.c: Add support for
|
||||||
|
removable serial devices (like USB serial). This support is enabled
|
||||||
|
by CONFIG_SERIAL_REMOVABLE and requires VBUS sensing support from
|
||||||
|
the board-specific logic.
|
||||||
|
|||||||
@@ -95,9 +95,7 @@ CONFIG_BOARD_LOOPSPERMSEC=16717
|
|||||||
#
|
#
|
||||||
# CONFIG_ARMV7M_TOOLCHAIN_ATOLLIC is not set
|
# CONFIG_ARMV7M_TOOLCHAIN_ATOLLIC is not set
|
||||||
# CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT is not set
|
# CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT is not set
|
||||||
# CONFIG_ARMV7M_TOOLCHAIN_CODEREDL is not set
|
|
||||||
# CONFIG_ARMV7M_TOOLCHAIN_CODEREDW is not set
|
# CONFIG_ARMV7M_TOOLCHAIN_CODEREDW is not set
|
||||||
# CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYL is not set
|
|
||||||
CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYW=y
|
CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYW=y
|
||||||
# CONFIG_ARMV7M_TOOLCHAIN_DEVKITARM is not set
|
# CONFIG_ARMV7M_TOOLCHAIN_DEVKITARM is not set
|
||||||
# CONFIG_ARMV7M_TOOLCHAIN_GNU_EABI is not set
|
# CONFIG_ARMV7M_TOOLCHAIN_GNU_EABI is not set
|
||||||
@@ -374,6 +372,7 @@ CONFIG_SPI_EXCHANGE=y
|
|||||||
# CONFIG_SERCOMM_CONSOLE is not set
|
# CONFIG_SERCOMM_CONSOLE is not set
|
||||||
CONFIG_SERIAL=y
|
CONFIG_SERIAL=y
|
||||||
# CONFIG_DEV_LOWCONSOLE is not set
|
# CONFIG_DEV_LOWCONSOLE is not set
|
||||||
|
CONFIG_SERIAL_REMOVABLE=y
|
||||||
# CONFIG_16550_UART is not set
|
# CONFIG_16550_UART is not set
|
||||||
CONFIG_ARCH_HAVE_USART2=y
|
CONFIG_ARCH_HAVE_USART2=y
|
||||||
CONFIG_MCU_SERIAL=y
|
CONFIG_MCU_SERIAL=y
|
||||||
@@ -458,6 +457,7 @@ CONFIG_CDCACM_PRODUCTSTR="CDC/ACM Serial"
|
|||||||
#
|
#
|
||||||
# System Logging
|
# System Logging
|
||||||
#
|
#
|
||||||
|
# CONFIG_SYSLOG_ENABLE is not set
|
||||||
CONFIG_SYSLOG=y
|
CONFIG_SYSLOG=y
|
||||||
CONFIG_SYSLOG_CHAR=y
|
CONFIG_SYSLOG_CHAR=y
|
||||||
CONFIG_SYSLOG_DEVPATH="/dev/ttyS0"
|
CONFIG_SYSLOG_DEVPATH="/dev/ttyS0"
|
||||||
@@ -686,6 +686,10 @@ CONFIG_NSH_NESTDEPTH=3
|
|||||||
# CONFIG_NSH_DISABLEBG is not set
|
# CONFIG_NSH_DISABLEBG is not set
|
||||||
CONFIG_NSH_CONSOLE=y
|
CONFIG_NSH_CONSOLE=y
|
||||||
# CONFIG_NSH_USBCONSOLE is not set
|
# CONFIG_NSH_USBCONSOLE is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# USB Trace Support
|
||||||
|
#
|
||||||
# CONFIG_NSH_CONDEV is not set
|
# CONFIG_NSH_CONDEV is not set
|
||||||
CONFIG_NSH_ARCHINIT=y
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
|
||||||
@@ -736,3 +740,7 @@ CONFIG_READLINE_ECHO=y
|
|||||||
# Sysinfo
|
# Sysinfo
|
||||||
#
|
#
|
||||||
# CONFIG_SYSTEM_SYSINFO is not set
|
# CONFIG_SYSTEM_SYSINFO is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# USB Monitor
|
||||||
|
#
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ config DEV_LOWCONSOLE
|
|||||||
---help---
|
---help---
|
||||||
Use the simple, low-level, write-only serial console driver (minimal support)
|
Use the simple, low-level, write-only serial console driver (minimal support)
|
||||||
|
|
||||||
|
config SERIAL_REMOVABLE
|
||||||
|
bool
|
||||||
|
|
||||||
config 16550_UART
|
config 16550_UART
|
||||||
bool "16550 UART Chip support"
|
bool "16550 UART Chip support"
|
||||||
default n
|
default n
|
||||||
|
|||||||
+131
-6
@@ -1,7 +1,7 @@
|
|||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* drivers/serial/serial.c
|
* drivers/serial/serial.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2011-2013 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
|
||||||
@@ -157,7 +157,11 @@ static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset)
|
|||||||
struct pollfd *fds = dev->fds[i];
|
struct pollfd *fds = dev->fds[i];
|
||||||
if (fds)
|
if (fds)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
fds->revents |= ((fds->events | (POLLERR|POLLHUP)) & eventset);
|
||||||
|
#else
|
||||||
fds->revents |= (fds->events & eventset);
|
fds->revents |= (fds->events & eventset);
|
||||||
|
#endif
|
||||||
if (fds->revents != 0)
|
if (fds->revents != 0)
|
||||||
{
|
{
|
||||||
fvdbg("Report events: %02x\n", fds->revents);
|
fvdbg("Report events: %02x\n", fds->revents);
|
||||||
@@ -219,6 +223,15 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch)
|
|||||||
uart_disabletxint(dev);
|
uart_disabletxint(dev);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
/* Check if the removable device is no longer connected */
|
||||||
|
|
||||||
|
if (dev->disconnected)
|
||||||
|
{
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if we were awakened by signal. */
|
/* Check if we were awakened by signal. */
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -279,6 +292,15 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||||||
ssize_t nread = buflen;
|
ssize_t nread = buflen;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
/* If the removable device is no longer connected, refuse to write to the device */
|
||||||
|
|
||||||
|
if (dev->disconnected)
|
||||||
|
{
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We may receive console writes through this path from interrupt handlers and
|
/* We may receive console writes through this path from interrupt handlers and
|
||||||
* from debug output in the IDLE task! In these cases, we will need to do things
|
* from debug output in the IDLE task! In these cases, we will need to do things
|
||||||
* a little differently.
|
* a little differently.
|
||||||
@@ -395,6 +417,15 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
|
|||||||
int16_t tail;
|
int16_t tail;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
/* If the removable device is no longer connected, refuse to read from the device */
|
||||||
|
|
||||||
|
if (dev->disconnected)
|
||||||
|
{
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Only one user can access dev->recv.tail at a time */
|
/* Only one user can access dev->recv.tail at a time */
|
||||||
|
|
||||||
ret = uart_takesem(&dev->recv.sem, true);
|
ret = uart_takesem(&dev->recv.sem, true);
|
||||||
@@ -525,9 +556,15 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
|
|||||||
ret = uart_takesem(&dev->recvsem, true);
|
ret = uart_takesem(&dev->recvsem, true);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
|
||||||
/* Was a signal received while waiting for data to be received? */
|
/* Was a signal received while waiting for data to be
|
||||||
|
* received? Was a removable device disconnected?
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
if (ret < 0 || dev->disconnected)
|
||||||
|
#else
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* POSIX requires that we return after a signal is received.
|
/* POSIX requires that we return after a signal is received.
|
||||||
* If some bytes were read, we need to return the number of bytes
|
* If some bytes were read, we need to return the number of bytes
|
||||||
@@ -541,7 +578,11 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
|
|||||||
* set the errno value appropriately.
|
* set the errno value appropriately.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
recvd = dev->disconnected ? -ENOTCONN : -EINTR;
|
||||||
|
#else
|
||||||
recvd = -EINTR;
|
recvd = -EINTR;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -656,12 +697,12 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup)
|
|||||||
|
|
||||||
if (ndx != dev->xmit.tail)
|
if (ndx != dev->xmit.tail)
|
||||||
{
|
{
|
||||||
eventset |= POLLOUT;
|
eventset |= (fds->events & POLLOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
uart_givesem(&dev->xmit.sem);
|
uart_givesem(&dev->xmit.sem);
|
||||||
|
|
||||||
/* Check if the receive buffer is empty
|
/* Check if the receive buffer is empty.
|
||||||
*
|
*
|
||||||
* Get exclusive access to the recv buffer indices. NOTE: that we do not
|
* Get exclusive access to the recv buffer indices. NOTE: that we do not
|
||||||
* let this wait be interrupted by a signal (we probably should, but that
|
* let this wait be interrupted by a signal (we probably should, but that
|
||||||
@@ -671,11 +712,20 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup)
|
|||||||
(void)uart_takesem(&dev->recv.sem, false);
|
(void)uart_takesem(&dev->recv.sem, false);
|
||||||
if (dev->recv.head != dev->recv.tail)
|
if (dev->recv.head != dev->recv.tail)
|
||||||
{
|
{
|
||||||
eventset |= POLLIN;
|
eventset |= (fds->events & POLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
uart_givesem(&dev->recv.sem);
|
uart_givesem(&dev->recv.sem);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
/* Check if a removable device has been disconnected. */
|
||||||
|
|
||||||
|
if (dev->disconnected)
|
||||||
|
{
|
||||||
|
eventset |= (POLLERR|POLLHUP);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (eventset)
|
if (eventset)
|
||||||
{
|
{
|
||||||
uart_pollnotify(dev, eventset);
|
uart_pollnotify(dev, eventset);
|
||||||
@@ -796,6 +846,15 @@ static int uart_open(FAR struct file *filep)
|
|||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
/* If the removable device is no longer connected, refuse to open the device */
|
||||||
|
|
||||||
|
if (dev->disconnected)
|
||||||
|
{
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If the port is the middle of closing, wait until the close is finished.
|
/* If the port is the middle of closing, wait until the close is finished.
|
||||||
* If a signal is received while we are waiting, then return EINTR.
|
* If a signal is received while we are waiting, then return EINTR.
|
||||||
*/
|
*/
|
||||||
@@ -915,10 +974,12 @@ int uart_register(FAR const char *path, FAR uart_dev_t *dev)
|
|||||||
|
|
||||||
void uart_datareceived(FAR uart_dev_t *dev)
|
void uart_datareceived(FAR uart_dev_t *dev)
|
||||||
{
|
{
|
||||||
/* Awaken any awaiting read() operations */
|
/* Is there a thread waiting for read data? */
|
||||||
|
|
||||||
if (dev->recvwaiting)
|
if (dev->recvwaiting)
|
||||||
{
|
{
|
||||||
|
/* Yes... wake it up */
|
||||||
|
|
||||||
dev->recvwaiting = false;
|
dev->recvwaiting = false;
|
||||||
(void)sem_post(&dev->recvsem);
|
(void)sem_post(&dev->recvsem);
|
||||||
}
|
}
|
||||||
@@ -942,8 +1003,12 @@ void uart_datareceived(FAR uart_dev_t *dev)
|
|||||||
|
|
||||||
void uart_datasent(FAR uart_dev_t *dev)
|
void uart_datasent(FAR uart_dev_t *dev)
|
||||||
{
|
{
|
||||||
|
/* Is there a thread waiting for space in xmit.buffer? */
|
||||||
|
|
||||||
if (dev->xmitwaiting)
|
if (dev->xmitwaiting)
|
||||||
{
|
{
|
||||||
|
/* Yes... wake it up */
|
||||||
|
|
||||||
dev->xmitwaiting = false;
|
dev->xmitwaiting = false;
|
||||||
(void)sem_post(&dev->xmitsem);
|
(void)sem_post(&dev->xmitsem);
|
||||||
}
|
}
|
||||||
@@ -953,4 +1018,64 @@ void uart_datasent(FAR uart_dev_t *dev)
|
|||||||
uart_pollnotify(dev, POLLOUT);
|
uart_pollnotify(dev, POLLOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: uart_connected
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Serial devices (like USB serial) can be removed. In that case, the "upper
|
||||||
|
* half" serial driver must be informed that there is no longer a valid serial
|
||||||
|
* channel associated with the driver.
|
||||||
|
*
|
||||||
|
* In this case, the driver will terminate all pending transfers wint ENOTCONN and
|
||||||
|
* will refuse all further transactions while the "lower half" is disconnected.
|
||||||
|
* The driver will continue to be registered, but will be in an unusable state.
|
||||||
|
*
|
||||||
|
* Conversely, the "upper half" serial driver needs to know when the serial
|
||||||
|
* device is reconnected so that it can resume normal operations.
|
||||||
|
*
|
||||||
|
* Assumptions/Limitations:
|
||||||
|
* This function may be called from an interrupt handler.
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
void uart_connected(FAR uart_dev_t *dev, bool connected)
|
||||||
|
{
|
||||||
|
/* Is the device disconnected? */
|
||||||
|
|
||||||
|
dev->disconnected = !connected;
|
||||||
|
if (!connected)
|
||||||
|
{
|
||||||
|
/* Yes.. wake up all waiting threads. Each thread should detect the
|
||||||
|
* disconnection and return the ENOTCONN error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Is there a thread waiting for space in xmit.buffer? */
|
||||||
|
|
||||||
|
if (dev->xmitwaiting)
|
||||||
|
{
|
||||||
|
/* Yes... wake it up */
|
||||||
|
|
||||||
|
dev->xmitwaiting = false;
|
||||||
|
(void)sem_post(&dev->xmitsem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is there a thread waiting for read data? */
|
||||||
|
|
||||||
|
if (dev->recvwaiting)
|
||||||
|
{
|
||||||
|
/* Yes... wake it up */
|
||||||
|
|
||||||
|
dev->recvwaiting = false;
|
||||||
|
(void)sem_post(&dev->recvsem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notify all poll/select waiters that and hangup/error occurred */
|
||||||
|
|
||||||
|
uart_pollnotify(dev, (POLLERR|POLLHUP));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ endif
|
|||||||
menuconfig PL2303
|
menuconfig PL2303
|
||||||
bool "Prolific PL2303 serial/USB converter emulation"
|
bool "Prolific PL2303 serial/USB converter emulation"
|
||||||
default n
|
default n
|
||||||
|
select SERIAL_REMOVABLE
|
||||||
---help---
|
---help---
|
||||||
This logic emulates the Prolific PL2303 serial/USB converter
|
This logic emulates the Prolific PL2303 serial/USB converter
|
||||||
|
|
||||||
@@ -222,6 +223,7 @@ endif
|
|||||||
menuconfig CDCACM
|
menuconfig CDCACM
|
||||||
bool "USB Modem (CDC ACM) support"
|
bool "USB Modem (CDC ACM) support"
|
||||||
default n
|
default n
|
||||||
|
select SERIAL_REMOVABLE
|
||||||
---help---
|
---help---
|
||||||
Enables USB Modem (CDC ACM) support
|
Enables USB Modem (CDC ACM) support
|
||||||
|
|
||||||
|
|||||||
+39
-8
@@ -570,6 +570,14 @@ static void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv)
|
|||||||
|
|
||||||
priv->config = CDCACM_CONFIGIDNONE;
|
priv->config = CDCACM_CONFIGIDNONE;
|
||||||
|
|
||||||
|
/* Inform the "upper half" driver that there is no (functional) USB
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
uart_connected(&priv->serdev, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Disable endpoints. This should force completion of all pending
|
/* Disable endpoints. This should force completion of all pending
|
||||||
* transfers.
|
* transfers.
|
||||||
*/
|
*/
|
||||||
@@ -731,10 +739,20 @@ static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config)
|
|||||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret);
|
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->nrdq++;
|
priv->nrdq++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We are successfully configured */
|
||||||
|
|
||||||
priv->config = config;
|
priv->config = config;
|
||||||
|
|
||||||
|
/* Inform the "upper half" driver that we are "open for business" */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
uart_connected(&priv->serdev, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
@@ -1575,12 +1593,20 @@ static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Reset the configuration */
|
/* Inform the "upper half serial driver that we have lost the USB serial
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
uart_connected(&priv->serdev, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Reset the configuration */
|
||||||
|
|
||||||
cdcacm_resetconfig(priv);
|
cdcacm_resetconfig(priv);
|
||||||
|
|
||||||
/* Clear out all data in the circular buffer */
|
/* Clear out all outgoing data in the circular buffer */
|
||||||
|
|
||||||
priv->serdev.xmit.head = 0;
|
priv->serdev.xmit.head = 0;
|
||||||
priv->serdev.xmit.tail = 0;
|
priv->serdev.xmit.tail = 0;
|
||||||
@@ -2045,12 +2071,17 @@ int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev)
|
|||||||
|
|
||||||
/* Initialize the serial driver sub-structure */
|
/* Initialize the serial driver sub-structure */
|
||||||
|
|
||||||
priv->serdev.recv.size = CONFIG_CDCACM_RXBUFSIZE;
|
/* The initial state is disconnected */
|
||||||
priv->serdev.recv.buffer = priv->rxbuffer;
|
|
||||||
priv->serdev.xmit.size = CONFIG_CDCACM_TXBUFSIZE;
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
priv->serdev.xmit.buffer = priv->txbuffer;
|
priv->serdev.disconnected = true;
|
||||||
priv->serdev.ops = &g_uartops;
|
#endif
|
||||||
priv->serdev.priv = priv;
|
priv->serdev.recv.size = CONFIG_CDCACM_RXBUFSIZE;
|
||||||
|
priv->serdev.recv.buffer = priv->rxbuffer;
|
||||||
|
priv->serdev.xmit.size = CONFIG_CDCACM_TXBUFSIZE;
|
||||||
|
priv->serdev.xmit.buffer = priv->txbuffer;
|
||||||
|
priv->serdev.ops = &g_uartops;
|
||||||
|
priv->serdev.priv = priv;
|
||||||
|
|
||||||
/* Initialize the USB class driver structure */
|
/* Initialize the USB class driver structure */
|
||||||
|
|
||||||
|
|||||||
+37
-8
@@ -983,6 +983,14 @@ static void usbclass_resetconfig(FAR struct pl2303_dev_s *priv)
|
|||||||
|
|
||||||
priv->config = PL2303_CONFIGIDNONE;
|
priv->config = PL2303_CONFIGIDNONE;
|
||||||
|
|
||||||
|
/* Inform the "upper half" driver that there is no (functional) USB
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
uart_connected(&priv->serdev, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Disable endpoints. This should force completion of all pending
|
/* Disable endpoints. This should force completion of all pending
|
||||||
* transfers.
|
* transfers.
|
||||||
*/
|
*/
|
||||||
@@ -1112,10 +1120,20 @@ static int usbclass_setconfig(FAR struct pl2303_dev_s *priv, uint8_t config)
|
|||||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret);
|
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret);
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->nrdq++;
|
priv->nrdq++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We are successfully configured */
|
||||||
|
|
||||||
priv->config = config;
|
priv->config = config;
|
||||||
|
|
||||||
|
/* Inform the "upper half" driver that we are "open for business" */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
uart_connected(&priv->serdev, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
@@ -1844,12 +1862,20 @@ static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Reset the configuration */
|
/* Inform the "upper half serial driver that we have lost the USB serial
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
uart_connected(&priv->serdev, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Reset the configuration */
|
||||||
|
|
||||||
usbclass_resetconfig(priv);
|
usbclass_resetconfig(priv);
|
||||||
|
|
||||||
/* Clear out all data in the circular buffer */
|
/* Clear out all outgoing data in the circular buffer */
|
||||||
|
|
||||||
priv->serdev.xmit.head = 0;
|
priv->serdev.xmit.head = 0;
|
||||||
priv->serdev.xmit.tail = 0;
|
priv->serdev.xmit.tail = 0;
|
||||||
@@ -2185,12 +2211,15 @@ int usbdev_serialinitialize(int minor)
|
|||||||
|
|
||||||
/* Initialize the serial driver sub-structure */
|
/* Initialize the serial driver sub-structure */
|
||||||
|
|
||||||
priv->serdev.recv.size = CONFIG_PL2303_RXBUFSIZE;
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
priv->serdev.recv.buffer = priv->rxbuffer;
|
priv->serdev.disconnected = true;
|
||||||
priv->serdev.xmit.size = CONFIG_PL2303_TXBUFSIZE;
|
#endif
|
||||||
priv->serdev.xmit.buffer = priv->txbuffer;
|
priv->serdev.recv.size = CONFIG_PL2303_RXBUFSIZE;
|
||||||
priv->serdev.ops = &g_uartops;
|
priv->serdev.recv.buffer = priv->rxbuffer;
|
||||||
priv->serdev.priv = priv;
|
priv->serdev.xmit.size = CONFIG_PL2303_TXBUFSIZE;
|
||||||
|
priv->serdev.xmit.buffer = priv->txbuffer;
|
||||||
|
priv->serdev.ops = &g_uartops;
|
||||||
|
priv->serdev.priv = priv;
|
||||||
|
|
||||||
/* Initialize the USB class driver structure */
|
/* Initialize the USB class driver structure */
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* include/nuttx/serial/serial.h
|
* include/nuttx/serial/serial.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2008, 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2008, 2012-2013 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
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
#include <nuttx/fs/fs.h>
|
#include <nuttx/fs/fs.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@@ -190,20 +191,23 @@ struct uart_ops_s
|
|||||||
|
|
||||||
struct uart_dev_s
|
struct uart_dev_s
|
||||||
{
|
{
|
||||||
uint8_t open_count; /* Number of times the device has been opened */
|
uint8_t open_count; /* Number of times the device has been opened */
|
||||||
volatile bool xmitwaiting; /* true: User waiting for space in xmit.buffer */
|
volatile bool xmitwaiting; /* true: User waiting for space in xmit.buffer */
|
||||||
volatile bool recvwaiting; /* true: User waiting for data in recv.buffer */
|
volatile bool recvwaiting; /* true: User waiting for data in recv.buffer */
|
||||||
bool isconsole; /* true: This is the serial console */
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
sem_t closesem; /* Locks out new open while close is in progress */
|
volatile bool disconnected; /* true: Removable device is not connected */
|
||||||
sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */
|
|
||||||
sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */
|
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
|
||||||
sem_t pollsem; /* Manages exclusive access to fds[] */
|
|
||||||
#endif
|
#endif
|
||||||
struct uart_buffer_s xmit; /* Describes transmit buffer */
|
bool isconsole; /* true: This is the serial console */
|
||||||
struct uart_buffer_s recv; /* Describes receive buffer */
|
sem_t closesem; /* Locks out new open while close is in progress */
|
||||||
FAR const struct uart_ops_s *ops; /* Arch-specific operations */
|
sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */
|
||||||
FAR void *priv; /* Used by the arch-specific logic */
|
sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */
|
||||||
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
|
sem_t pollsem; /* Manages exclusive access to fds[] */
|
||||||
|
#endif
|
||||||
|
struct uart_buffer_s xmit; /* Describes transmit buffer */
|
||||||
|
struct uart_buffer_s recv; /* Describes receive buffer */
|
||||||
|
FAR const struct uart_ops_s *ops; /* Arch-specific operations */
|
||||||
|
FAR void *priv; /* Used by the arch-specific logic */
|
||||||
|
|
||||||
/* The following is a list if poll structures of threads waiting for
|
/* The following is a list if poll structures of threads waiting for
|
||||||
* driver events. The 'struct pollfd' reference for each open is also
|
* driver events. The 'struct pollfd' reference for each open is also
|
||||||
@@ -213,26 +217,27 @@ struct uart_dev_s
|
|||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
struct pollfd *fds[CONFIG_SERIAL_NPOLLWAITERS];
|
struct pollfd *fds[CONFIG_SERIAL_NPOLLWAITERS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct uart_dev_s uart_dev_t;
|
typedef struct uart_dev_s uart_dev_t;
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* Public Functions
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
#define EXTERN extern "C"
|
#define EXTERN extern "C"
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#else
|
#else
|
||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: uart_register
|
* Name: uart_register
|
||||||
*
|
*
|
||||||
@@ -241,7 +246,7 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
EXTERN int uart_register(FAR const char *path, FAR uart_dev_t *dev);
|
int uart_register(FAR const char *path, FAR uart_dev_t *dev);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: uart_xmitchars
|
* Name: uart_xmitchars
|
||||||
@@ -254,7 +259,7 @@ EXTERN int uart_register(FAR const char *path, FAR uart_dev_t *dev);
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
EXTERN void uart_xmitchars(FAR uart_dev_t *dev);
|
void uart_xmitchars(FAR uart_dev_t *dev);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: uart_receivechars
|
* Name: uart_receivechars
|
||||||
@@ -267,7 +272,7 @@ EXTERN void uart_xmitchars(FAR uart_dev_t *dev);
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
EXTERN void uart_recvchars(FAR uart_dev_t *dev);
|
void uart_recvchars(FAR uart_dev_t *dev);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: uart_datareceived
|
* Name: uart_datareceived
|
||||||
@@ -279,7 +284,7 @@ EXTERN void uart_recvchars(FAR uart_dev_t *dev);
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
EXTERN void uart_datareceived(FAR uart_dev_t *dev);
|
void uart_datareceived(FAR uart_dev_t *dev);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: uart_datasent
|
* Name: uart_datasent
|
||||||
@@ -292,7 +297,31 @@ EXTERN void uart_datareceived(FAR uart_dev_t *dev);
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
EXTERN void uart_datasent(FAR uart_dev_t *dev);
|
void uart_datasent(FAR uart_dev_t *dev);
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: uart_connected
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Serial devices (like USB serial) can be removed. In that case, the "upper
|
||||||
|
* half" serial driver must be informed that there is no longer a valid serial
|
||||||
|
* channel associated with the driver.
|
||||||
|
*
|
||||||
|
* In this case, the driver will terminate all pending transfers wint ENOTCONN and
|
||||||
|
* will refuse all further transactions while the "lower half" is disconnected.
|
||||||
|
* The driver will continue to be registered, but will be in an unusable state.
|
||||||
|
*
|
||||||
|
* Conversely, the "upper half" serial driver needs to know when the serial
|
||||||
|
* device is reconnected so that it can resume normal operations.
|
||||||
|
*
|
||||||
|
* Assumptions/Limitations:
|
||||||
|
* This function may be called from an interrupt handler.
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_REMOVABLE
|
||||||
|
void uart_connected(FAR uart_dev_t *dev, bool connected);
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|||||||
Reference in New Issue
Block a user