aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-06-17 07:49:08 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-06-17 07:49:08 +0000
commit25ac1fcadfb483d74226f5e020ed8057896de6f2 (patch)
tree823dd8b48ba578c452af056470a4d85dbef5685d /os
parentc6914081835f10258d873af8526ae405ffe5b25c (diff)
downloadChibiOS-25ac1fcadfb483d74226f5e020ed8057896de6f2.tar.gz
ChibiOS-25ac1fcadfb483d74226f5e020ed8057896de6f2.tar.bz2
ChibiOS-25ac1fcadfb483d74226f5e020ed8057896de6f2.zip
USB driver API improvements. Revision of the low level drivers.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4284 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/include/usb.h78
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.c135
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.h10
-rw-r--r--os/hal/platforms/STM32/USBv1/usb_lld.c110
-rw-r--r--os/hal/platforms/STM32/USBv1/usb_lld.h10
-rw-r--r--os/hal/src/usb.c158
6 files changed, 193 insertions, 308 deletions
diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h
index ddf8cb321..a0a7298e0 100644
--- a/os/hal/include/usb.h
+++ b/os/hal/include/usb.h
@@ -386,76 +386,6 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
#define usbGetReceiveStatusI(usbp, ep) ((usbp)->receiving & (1 << (ep)))
/**
- * @brief Prepares for a receive transaction on an OUT endpoint.
- * @pre In order to use this function the endpoint must have been
- * initialized in transaction mode.
- * @post The endpoint is ready for @p usbStartReceiveI().
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the received data
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-#define usbPrepareReceive(usbp, ep, buf, n) \
- usb_lld_prepare_receive(usbp, ep, buf, n)
-
-/**
- * @brief Prepares for a transmit transaction on an IN endpoint.
- * @pre In order to use this function the endpoint must have been
- * initialized in transaction mode.
- * @post The endpoint is ready for @p usbStartTransmitI().
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the data to be transmitted
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-#define usbPrepareTransmit(usbp, ep, buf, n) \
- usb_lld_prepare_transmit(usbp, ep, buf, n)
-
-/**
- * @brief Prepares for a receive transaction on an OUT endpoint.
- * @pre In order to use this function the endpoint must have been
- * initialized in transaction mode.
- * @post The endpoint is ready for @p usbStartReceiveI().
- * @note The receive transaction size is equal to the space in the queue
- * rounded to the lower multiple of a packet size. Make sure there
- * is room for at least one packet in the queue before starting
- * the receive operation.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] iq input queue to be filled with incoming data
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-#define usbPrepareQueuedReceive(usbp, ep, iq, n) \
- usb_lld_prepare_queued_receive(usbp, ep, iq, n)
-
-/**
- * @brief Prepares for a transmit transaction on an IN endpoint.
- * @pre In order to use this function the endpoint must have been
- * initialized in transaction mode.
- * @post The endpoint is ready for @p usbStartTransmitI().
- * @note The transmit transaction size is equal to the data contained
- * in the queue.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] oq output queue to be fetched for outgoing data
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-#define usbPrepareQueuedTransmit(usbp, ep, oq, n) \
- usb_lld_prepare_queued_transmit(usbp, ep, oq, n)
-
-/**
* @brief Returns the exact size of a receive transaction.
* @details The received size can be different from the size specified in
* @p usbStartReceiveI() because the last packet could have a size
@@ -604,6 +534,14 @@ extern "C" {
const USBEndpointConfig *epcp);
void usbDisableEndpointsI(USBDriver *usbp);
void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf);
+ void usbPrepareReceive(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n);
+ void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n);
+ void usbPrepareQueuedReceive(USBDriver *usbp, usbep_t ep,
+ InputQueue *iqp, size_t n);
+ void usbPrepareQueuedTransmit(USBDriver *usbp, usbep_t ep,
+ OutputQueue *oqp, size_t n);
bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep);
bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep);
bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep);
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c
index 005bfdede..68f4714fb 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.c
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c
@@ -188,61 +188,6 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
}
/**
- * @brief Prepares for a receive transaction on an OUT endpoint.
- * @post The endpoint is ready for @p usbStartReceiveI().
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-static void otg_prepare_receive(USBDriver *usbp, usbep_t ep, size_t n) {
- uint32_t pcnt;
- USBOutEndpointState *osp = usbp->epc[ep]->out_state;
-
- osp->rxsize = n;
- osp->rxcnt = 0;
-
- /* Transfer initialization.*/
- pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
- OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
- DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
-}
-
-/**
- * @brief Prepares for a transmit transaction on an IN endpoint.
- * @post The endpoint is ready for @p usbStartTransmitI().
- * @note The transmit transaction size is equal to the data contained
- * in the queue.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-static void otg_prepare_transmit(USBDriver *usbp, usbep_t ep, size_t n) {
- uint32_t pcnt;
- USBInEndpointState *isp = usbp->epc[ep]->in_state;
-
- isp->txsize = n;
- isp->txcnt = 0;
-
- /* Transfer initialization.*/
- if (n == 0) {
- /* Special case, sending zero size packet.*/
- OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
- }
- else {
- /* Normal case.*/
- pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
- OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
- DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
- }
-}
-
-/**
* @brief Pushes a series of words into a FIFO.
*
* @param[in] fifop pointer to the FIFO register
@@ -963,18 +908,19 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the received data
- * @param[in] n maximum number of bytes to copy
*
* @notapi
*/
-void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
+void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) {
+ uint32_t pcnt;
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
- osp->rxqueued = FALSE;
- osp->mode.linear.rxbuf = buf;
- otg_prepare_receive(usbp, ep, n);
+ /* Transfer initialization.*/
+ pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
+ usbp->epc[ep]->out_maxsize;
+ OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
+ DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
+
}
/**
@@ -982,64 +928,25 @@ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the data to be transmitted
- * @param[in] n maximum number of bytes to copy
*
* @notapi
*/
-void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
+void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
- isp->txqueued = FALSE;
- isp->mode.linear.txbuf = buf;
- otg_prepare_transmit(usbp, ep, n);
-}
-
-/**
- * @brief Prepares for a receive transaction on an OUT endpoint.
- * @post The endpoint is ready for @p usbStartReceiveI().
- * @note The receive transaction size is equal to the space in the queue
- * rounded to the lower multiple of a packet size. Make sure there
- * is room for at least one packet in the queue before starting
- * the receive operation.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] iq input queue to be filled with incoming data
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
- InputQueue *iq, size_t n) {
- USBOutEndpointState *osp = usbp->epc[ep]->out_state;
-
- osp->rxqueued = TRUE;
- osp->mode.queue.rxqueue = iq;
- otg_prepare_receive(usbp, ep, n);
-}
-
-/**
- * @brief Prepares for a transmit transaction on an IN endpoint.
- * @post The endpoint is ready for @p usbStartTransmitI().
- * @note The transmit transaction size is equal to the data contained
- * in the queue.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] oq output queue to be fetched for outgoing data
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
- OutputQueue *oq, size_t n) {
- USBInEndpointState *isp = usbp->epc[ep]->in_state;
+ /* Transfer initialization.*/
+ if (isp->txsize == 0) {
+ /* Special case, sending zero size packet.*/
+ OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
+ }
+ else {
+ /* Normal case.*/
+ uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) /
+ usbp->epc[ep]->in_maxsize;
+ OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
+ DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
+ }
- isp->txqueued = TRUE;
- isp->mode.queue.txqueue = oq;
- otg_prepare_transmit(usbp, ep, n);
}
/**
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h
index d9b013976..23e41d6e8 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.h
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h
@@ -397,14 +397,8 @@ extern "C" {
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
- void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n);
- void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n);
- void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
- InputQueue *iq, size_t n);
- void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
- OutputQueue *oq, size_t n);
+ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep);
+ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep);
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.c b/os/hal/platforms/STM32/USBv1/usb_lld.c
index 0d61b68c7..7bccf4e4d 100644
--- a/os/hal/platforms/STM32/USBv1/usb_lld.c
+++ b/os/hal/platforms/STM32/USBv1/usb_lld.c
@@ -259,30 +259,6 @@ static void usb_packet_write_from_queue(stm32_usb_descriptor_t *udp,
port_unlock();
}
-/**
- * @brief Prepares for a receive transaction on an OUT endpoint.
- * @post The endpoint is ready for @p usbStartReceiveI().
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-static void usb_prepare_receive(USBDriver *usbp, usbep_t ep, size_t n) {
- USBOutEndpointState *osp = usbp->epc[ep]->out_state;
-
- osp->rxsize = n;
- osp->rxcnt = 0;
-
- /* Transfer initialization.*/
- if (osp->rxsize == 0) /* Special case for zero sized packets.*/
- osp->rxpkts = 1;
- else
- osp->rxpkts = (uint16_t)((n + usbp->epc[ep]->out_maxsize - 1) /
- usbp->epc[ep]->out_maxsize);
-}
-
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
@@ -704,18 +680,18 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the received data
- * @param[in] n maximum number of bytes to copy
*
* @notapi
*/
-void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
+void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) {
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
- osp->rxqueued = FALSE;
- osp->mode.linear.rxbuf = buf;
- usb_prepare_receive(usbp, ep, n);
+ /* Transfer initialization.*/
+ if (osp->rxsize == 0) /* Special case for zero sized packets.*/
+ osp->rxpkts = 1;
+ else
+ osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
+ usbp->epc[ep]->out_maxsize);
}
/**
@@ -728,75 +704,21 @@ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
*
* @notapi
*/
-void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
- USBInEndpointState *isp = usbp->epc[ep]->in_state;
-
- isp->txqueued = FALSE;
- isp->mode.linear.txbuf = buf;
- isp->txsize = n;
- isp->txcnt = 0;
-
- /* Transfer initialization.*/
- if (n > (size_t)usbp->epc[ep]->in_maxsize)
- n = (size_t)usbp->epc[ep]->in_maxsize;
-
- usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep),
- isp->mode.linear.txbuf, n);
-}
-
-/**
- * @brief Prepares for a receive transaction on an OUT endpoint.
- * @post The endpoint is ready for @p usbStartReceiveI().
- * @note The receive transaction size is equal to the space in the queue
- * rounded to the lower multiple of a packet size. Make sure there
- * is room for at least one packet in the queue before starting
- * the receive operation.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] iq input queue to be filled with incoming data
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
- InputQueue *iq, size_t n) {
- USBOutEndpointState *osp = usbp->epc[ep]->out_state;
-
- osp->rxqueued = TRUE;
- osp->mode.queue.rxqueue = iq;
- usb_prepare_receive(usbp, ep, n);
-}
-
-/**
- * @brief Prepares for a transmit transaction on an IN endpoint.
- * @post The endpoint is ready for @p usbStartTransmitI().
- * @note The transmit transaction size is equal to the data contained
- * in the queue.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] oq output queue to be fetched for outgoing data
- * @param[in] n maximum number of bytes to copy
- *
- * @special
- */
-void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
- OutputQueue *oq, size_t n) {
+void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
+ size_t n;
USBInEndpointState *isp = usbp->epc[ep]->in_state;
- isp->txqueued = TRUE;
- isp->mode.queue.txqueue = oq;
- isp->txsize = n;
- isp->txcnt = 0;
-
/* Transfer initialization.*/
+ n = isp->txsize;
if (n > (size_t)usbp->epc[ep]->in_maxsize)
n = (size_t)usbp->epc[ep]->in_maxsize;
- usb_packet_write_from_queue(USB_GET_DESCRIPTOR(ep),
- isp->mode.queue.txqueue, n);
+ if (isp->txqueued)
+ usb_packet_write_from_queue(USB_GET_DESCRIPTOR(ep),
+ isp->mode.queue.txqueue, n);
+ else
+ usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep),
+ isp->mode.linear.txbuf, n);
}
/**
diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.h b/os/hal/platforms/STM32/USBv1/usb_lld.h
index 1520e97c6..f8c2b32f5 100644
--- a/os/hal/platforms/STM32/USBv1/usb_lld.h
+++ b/os/hal/platforms/STM32/USBv1/usb_lld.h
@@ -407,14 +407,8 @@ extern "C" {
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
- void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n);
- void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n);
- void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
- InputQueue *iq, size_t n);
- void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
- OutputQueue *oq, size_t n);
+ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep);
+ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep);
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c
index fa79ea0c1..7f9d0456d 100644
--- a/os/hal/src/usb.c
+++ b/os/hal/src/usb.c
@@ -353,12 +353,125 @@ void usbDisableEndpointsI(USBDriver *usbp) {
}
/**
+ * @brief Prepares for a receive transaction on an OUT endpoint.
+ * @pre In order to use this function the endpoint must have been
+ * initialized in transaction mode.
+ * @post The endpoint is ready for @p usbStartReceiveI().
+ * @note This function can be called both in ISR and thread context.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the received data
+ * @param[in] n transaction size
+ *
+ * @special
+ */
+void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
+ USBOutEndpointState *osp = usbp->epc[ep]->out_state;
+
+ osp->rxqueued = FALSE;
+ osp->mode.linear.rxbuf = buf;
+ osp->rxsize = n;
+ osp->rxcnt = 0;
+
+ usb_lld_prepare_receive(usbp, ep);
+}
+
+/**
+ * @brief Prepares for a transmit transaction on an IN endpoint.
+ * @pre In order to use this function the endpoint must have been
+ * initialized in transaction mode.
+ * @post The endpoint is ready for @p usbStartTransmitI().
+ * @note This function can be called both in ISR and thread context.
+ * @note The queue must contain at least the amount of data specified
+ * as transaction size.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] buf buffer where to fetch the data to be transmitted
+ * @param[in] n transaction size
+ *
+ * @special
+ */
+void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n) {
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ isp->txqueued = FALSE;
+ isp->mode.linear.txbuf = buf;
+ isp->txsize = n;
+ isp->txcnt = 0;
+
+ usb_lld_prepare_transmit(usbp, ep);
+}
+
+/**
+ * @brief Prepares for a receive transaction on an OUT endpoint.
+ * @pre In order to use this function the endpoint must have been
+ * initialized in transaction mode.
+ * @post The endpoint is ready for @p usbStartReceiveI().
+ * @note This function can be called both in ISR and thread context.
+ * @note The queue must have enough free space to accommodate the
+ * specified transaction size rounded to the next packet size
+ * boundary. For example if the transaction size is 1 and the
+ * packet size is 64 then the queue must have space for at least
+ * 64 bytes.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] iqp input queue to be filled with incoming data
+ * @param[in] n transaction size
+ *
+ * @special
+ */
+void usbPrepareQueuedReceive(USBDriver *usbp, usbep_t ep,
+ InputQueue *iqp, size_t n) {
+ USBOutEndpointState *osp = usbp->epc[ep]->out_state;
+
+ osp->rxqueued = TRUE;
+ osp->mode.queue.rxqueue = iqp;
+ osp->rxsize = n;
+ osp->rxcnt = 0;
+
+ usb_lld_prepare_receive(usbp, ep);
+}
+
+/**
+ * @brief Prepares for a transmit transaction on an IN endpoint.
+ * @pre In order to use this function the endpoint must have been
+ * initialized in transaction mode.
+ * @post The endpoint is ready for @p usbStartTransmitI().
+ * @note This function can be called both in ISR and thread context.
+ * @note The transmit transaction size is equal to the data contained
+ * in the queue.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] oqp output queue to be fetched for outgoing data
+ * @param[in] n transaction size
+ *
+ * @special
+ */
+void usbPrepareQueuedTransmit(USBDriver *usbp, usbep_t ep,
+ OutputQueue *oqp, size_t n) {
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ isp->txqueued = TRUE;
+ isp->mode.queue.txqueue = oqp;
+ isp->txsize = n;
+ isp->txcnt = 0;
+
+ usb_lld_prepare_transmit(usbp, ep);
+}
+
+/**
* @brief Starts a receive transaction on an OUT endpoint.
* @post The endpoint callback is invoked when the transfer has been
* completed.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
+ *
* @return The operation status.
* @retval FALSE Operation started successfully.
* @retval TRUE Endpoint busy, operation not started.
@@ -385,6 +498,7 @@ bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
+ *
* @return The operation status.
* @retval FALSE Operation started successfully.
* @retval TRUE Endpoint busy, operation not started.
@@ -409,6 +523,7 @@ bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
+ *
* @return The operation status.
* @retval FALSE Endpoint stalled.
* @retval TRUE Endpoint busy, not stalled.
@@ -432,6 +547,7 @@ bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep) {
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
+ *
* @return The operation status.
* @retval FALSE Endpoint stalled.
* @retval TRUE Endpoint busy, not stalled.
@@ -526,15 +642,19 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
if (usbp->ep0n > 0) {
/* Starts the transmit phase.*/
usbp->ep0state = USB_EP0_TX;
- usb_lld_prepare_transmit(usbp, 0, usbp->ep0next, usbp->ep0n);
- usb_lld_start_in(usbp, 0);
+ usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n);
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, 0);
+ chSysUnlockFromIsr();
}
else {
/* No transmission phase, directly receiving the zero sized status
packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
- usb_lld_prepare_receive(usbp, 0, NULL, 0);
- usb_lld_start_out(usbp, 0);
+ usbPrepareReceive(usbp, 0, NULL, 0);
+ chSysLockFromIsr();
+ usbStartReceiveI(usbp, 0);
+ chSysUnlockFromIsr();
}
}
else {
@@ -542,15 +662,19 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
if (usbp->ep0n > 0) {
/* Starts the receive phase.*/
usbp->ep0state = USB_EP0_RX;
- usb_lld_prepare_receive(usbp, 0, usbp->ep0next, usbp->ep0n);
- usb_lld_start_out(usbp, 0);
+ usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n);
+ chSysLockFromIsr();
+ usbStartReceiveI(usbp, 0);
+ chSysUnlockFromIsr();
}
else {
/* No receive phase, directly sending the zero sized status
packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
- usb_lld_prepare_transmit(usbp, 0, NULL, 0);
- usb_lld_start_in(usbp, 0);
+ usbPrepareTransmit(usbp, 0, NULL, 0);
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, 0);
+ chSysUnlockFromIsr();
}
}
}
@@ -577,15 +701,19 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
transmitted.*/
if ((usbp->ep0n < max) &&
((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
- usb_lld_prepare_transmit(usbp, 0, NULL, 0);
- usb_lld_start_in(usbp, 0);
+ usbPrepareTransmit(usbp, 0, NULL, 0);
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, 0);
+ chSysUnlockFromIsr();
return;
}
/* Transmit phase over, receiving the zero sized status packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
- usb_lld_prepare_receive(usbp, 0, NULL, 0);
- usb_lld_start_out(usbp, 0);
+ usbPrepareReceive(usbp, 0, NULL, 0);
+ chSysLockFromIsr();
+ usbStartReceiveI(usbp, 0);
+ chSysUnlockFromIsr();
return;
case USB_EP0_SENDING_STS:
/* Status packet sent, invoking the callback if defined.*/
@@ -622,8 +750,10 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
case USB_EP0_RX:
/* Receive phase over, sending the zero sized status packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
- usb_lld_prepare_transmit(usbp, 0, NULL, 0);
- usb_lld_start_in(usbp, 0);
+ usbPrepareTransmit(usbp, 0, NULL, 0);
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, 0);
+ chSysUnlockFromIsr();
return;
case USB_EP0_WAITING_STS:
/* Status packet received, it must be zero sized, invoking the callback