diff options
author | px4dev <px4@purgatory.org> | 2013-02-06 21:38:33 -0800 |
---|---|---|
committer | px4dev <px4@purgatory.org> | 2013-02-06 21:38:33 -0800 |
commit | d573cca61bd3e377a1c03abc36f88c3886b21e59 (patch) | |
tree | c8ffec75806b46658bbe707d16b6eb45008981ca /nuttx/drivers/usbdev/cdcacm.c | |
parent | 3e5cd26777aa209d6568036d43b33b543a364bee (diff) | |
parent | 049c93446561c6ad3e59183c139f3916230ddee5 (diff) | |
download | px4-firmware-d573cca61bd3e377a1c03abc36f88c3886b21e59.tar.gz px4-firmware-d573cca61bd3e377a1c03abc36f88c3886b21e59.tar.bz2 px4-firmware-d573cca61bd3e377a1c03abc36f88c3886b21e59.zip |
Merge commit '049c93446561c6ad3e59183c139f3916230ddee5' into nuttx-merge-5596
This merges NuttX 6.25 with one post-release bugfix.
Diffstat (limited to 'nuttx/drivers/usbdev/cdcacm.c')
-rw-r--r-- | nuttx/drivers/usbdev/cdcacm.c | 137 |
1 files changed, 127 insertions, 10 deletions
diff --git a/nuttx/drivers/usbdev/cdcacm.c b/nuttx/drivers/usbdev/cdcacm.c index 97c9d7c77..cb8679976 100644 --- a/nuttx/drivers/usbdev/cdcacm.c +++ b/nuttx/drivers/usbdev/cdcacm.c @@ -1,7 +1,7 @@ /**************************************************************************** * drivers/usbdev/cdcacm.c * - * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -188,6 +188,12 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver, size_t outlen); static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +#ifdef CONFIG_SERIAL_REMOVABLE +static void cdcacm_suspend(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +static void cdcacm_resume(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev); +#endif /* UART Operations **********************************************************/ @@ -211,8 +217,13 @@ static const struct usbdevclass_driverops_s g_driverops = cdcacm_unbind, /* unbind */ cdcacm_setup, /* setup */ cdcacm_disconnect, /* disconnect */ +#ifdef CONFIG_SERIAL_REMOVABLE + cdcacm_suspend, /* suspend */ + cdcacm_resume, /* resume */ +#else NULL, /* suspend */ NULL, /* resume */ +#endif }; /* Serial port **************************************************************/ @@ -570,6 +581,14 @@ static void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv) 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 * transfers. */ @@ -731,10 +750,20 @@ static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config) usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret); goto errout; } + priv->nrdq++; } + /* We are successfully configured */ + 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; errout: @@ -823,6 +852,7 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep, { usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-req->result); } + irqrestore(flags); } @@ -932,6 +962,7 @@ static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver, ret = -ENOMEM; goto errout; } + priv->ctrlreq->callback = cdcacm_ep0incomplete; /* Pre-allocate all endpoints... the endpoints will not be functional @@ -1575,12 +1606,20 @@ static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver, } #endif - /* Reset the configuration */ + /* Inform the "upper half serial driver that we have lost the USB serial + * connection. + */ flags = irqsave(); +#ifdef CONFIG_SERIAL_REMOVABLE + uart_connected(&priv->serdev, false); +#endif + + /* Reset the configuration */ + 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.tail = 0; @@ -1596,6 +1635,79 @@ static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver, } /**************************************************************************** + * Name: cdcacm_suspend + * + * Description: + * Handle the USB suspend event. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_REMOVABLE +static void cdcacm_suspend(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct cdcacm_dev_s *priv; + + usbtrace(TRACE_CLASSSUSPEND, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct cdcacm_driver_s*)driver)->dev; + + /* And let the "upper half" driver now that we are suspended */ + + uart_connected(&priv->serdev, false); +} +#endif + +/**************************************************************************** + * Name: cdcacm_resume + * + * Description: + * Handle the USB resume event. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_REMOVABLE +static void cdcacm_resume(FAR struct usbdevclass_driver_s *driver, + FAR struct usbdev_s *dev) +{ + FAR struct cdcacm_dev_s *priv; + + usbtrace(TRACE_CLASSRESUME, 0); + +#ifdef CONFIG_DEBUG + if (!driver || !dev) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); + return; + } +#endif + + /* Extract reference to private data */ + + priv = ((FAR struct cdcacm_driver_s*)driver)->dev; + + /* Are we still configured? */ + + if (priv->config != CDCACM_CONFIGIDNONE) + { + /* Yes.. let the "upper half" know that have resumed */ + + uart_connected(&priv->serdev, true); + } +} +#endif + +/**************************************************************************** * Serial Device Methods ****************************************************************************/ @@ -2045,12 +2157,17 @@ int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev) /* Initialize the serial driver sub-structure */ - 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; + /* The initial state is disconnected */ + +#ifdef CONFIG_SERIAL_REMOVABLE + priv->serdev.disconnected = true; +#endif + 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 */ @@ -2148,7 +2265,7 @@ int cdcacm_initialize(int minor, FAR void **handle) * * Description: * Un-initialize the USB storage class driver. This function is used - * internally by the USB composite driver to unitialized the CDC/ACM + * internally by the USB composite driver to unitialize the CDC/ACM * driver. This same interface is available (with an untyped input * parameter) when the CDC/ACM driver is used standalone. * |