aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/include/usb.h22
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.c80
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.h2
-rw-r--r--os/hal/src/serial_usb.c48
-rw-r--r--os/hal/src/usb.c159
5 files changed, 116 insertions, 195 deletions
diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h
index 4aed90a08..cd2384b26 100644
--- a/os/hal/include/usb.h
+++ b/os/hal/include/usb.h
@@ -412,9 +412,9 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
* @param[in] usbp pointer to the @p USBDriver object
* @return The current frame number.
*
- * @api
+ * @xclass
*/
-#define usbGetFrameNumber(usbp) usb_lld_get_frame_number(usbp)
+#define usbGetFrameNumberX(usbp) usb_lld_get_frame_number(usbp)
/**
* @brief Returns the status of an IN endpoint.
@@ -454,9 +454,9 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
* @param[in] ep endpoint number
* @return Received data size.
*
- * @iclass
+ * @xclass
*/
-#define usbGetReceiveTransactionSizeI(usbp, ep) \
+#define usbGetReceiveTransactionSizeX(usbp, ep) \
usb_lld_get_transaction_size(usbp, ep)
/**
@@ -469,7 +469,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
* @param[in] n number of bytes to be transferred
* @param[in] endcb callback to be invoked after the transfer or @p NULL
*
- * @api
+ * @special
*/
#define usbSetupTransfer(usbp, buf, n, endcb) { \
(usbp)->ep0next = (buf); \
@@ -580,7 +580,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
} \
osalSysLockFromISR(); \
osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \
- usbGetReceiveTransactionSizeI(usbp, ep)); \
+ usbGetReceiveTransactionSizeX(usbp, ep)); \
osalSysUnlockFromISR(); \
}
#else
@@ -608,12 +608,10 @@ 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);
- bool usbStartReceiveI(USBDriver *usbp, usbep_t ep);
- bool usbStartTransmitI(USBDriver *usbp, usbep_t ep);
+ void usbStartReceiveI(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n);
+ void usbStartTransmitI(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n);
#if USB_USE_WAIT == TRUE
msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n);
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n);
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
index a4a784d2a..e0d817d05 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
@@ -369,7 +369,6 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
cover the remaining.*/
isp->txsize = isp->totsize - isp->txsize;
isp->txcnt = 0;
- usb_lld_prepare_transmit(usbp, ep);
osalSysLockFromISR();
usb_lld_start_in(usbp, ep);
osalSysUnlockFromISR();
@@ -415,13 +414,14 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
/* Receive transfer complete.*/
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
- if (osp->rxsize < osp->totsize) {
+ /* A short packet always terminates a transaction.*/
+ if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) &&
+ (osp->rxsize < osp->totsize)) {
/* In case the transaction covered only part of the total transfer
then another transaction is immediately started in order to
cover the remaining.*/
osp->rxsize = osp->totsize - osp->rxsize;
osp->rxcnt = 0;
- usb_lld_prepare_receive(usbp, ep);
osalSysLockFromISR();
usb_lld_start_out(usbp, ep);
osalSysUnlockFromISR();
@@ -476,7 +476,6 @@ static void otg_isoc_in_failed_handler(USBDriver *usbp) {
*
* @notapi
*/
-
static void otg_isoc_out_failed_handler(USBDriver *usbp) {
usbep_t ep;
stm32_otg_t *otgp = usbp->otg;
@@ -1135,38 +1134,57 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
}
/**
- * @brief Prepares for a receive operation.
+ * @brief Starts a receive operation on an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
-void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) {
- uint32_t pcnt;
+void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
+ uint32_t pcnt, rxsize;
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
/* Transfer initialization.*/
osp->totsize = osp->rxsize;
- if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
+ if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
osp->rxsize = EP0_MAX_OUTSIZE;
- pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
- usbp->epc[ep]->out_maxsize;
+ /* Transaction size is rounded to a multiple of packet size because the
+ following requirement in the RM:
+ "For OUT transfers, the transfer size field in the endpoint's transfer
+ size register must be a multiple of the maximum packet size of the
+ endpoint, adjusted to the Word boundary".*/
+ pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) /
+ usbp->epc[ep]->out_maxsize;
+ rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU;
+
+ /*Setting up transaction parameters in DOEPTSIZ.*/
usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
- DOEPTSIZ_XFRSIZ(osp->rxsize);
+ DOEPTSIZ_XFRSIZ(rxsize);
+
+ /* Special case of isochronous endpoint.*/
+ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
+ /* Odd/even bit toggling for isochronous endpoint.*/
+ if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM;
+ else
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM;
+ }
+ /* Starting operation.*/
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK;
}
/**
- * @brief Prepares for a transmit operation.
+ * @brief Starts a transmit operation on an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
-void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
+void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
/* Transfer initialization.*/
@@ -1176,7 +1194,7 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
}
else {
- if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
+ if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
isp->txsize = EP0_MAX_INSIZE;
/* Normal case.*/
@@ -1186,39 +1204,8 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) |
DIEPTSIZ_XFRSIZ(isp->txsize);
}
-}
-
-/**
- * @brief Starts a receive operation on an OUT endpoint.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- *
- * @notapi
- */
-void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
-
- if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
- /* Odd/even bit toggling for isochronous endpoint.*/
- if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
- usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM;
- else
- usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM;
- }
-
- usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK;
-}
-
-/**
- * @brief Starts a transmit operation on an IN endpoint.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- *
- * @notapi
- */
-void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
+ /* Special case of isochronous endpoint.*/
if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
/* Odd/even bit toggling.*/
if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
@@ -1227,6 +1214,7 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM;
}
+ /* Starting operation.*/
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK;
usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep);
}
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
index c90424c36..85038a9e2 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
@@ -540,8 +540,6 @@ 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);
- 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/serial_usb.c b/os/hal/src/serial_usb.c
index a5e8247a8..d4525c52f 100644
--- a/os/hal/src/serial_usb.c
+++ b/os/hal/src/serial_usb.c
@@ -146,13 +146,8 @@ static void ibnotify(io_buffers_queue_t *bqp) {
uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue);
if (buf != NULL) {
/* Buffer found, starting a new transaction.*/
- osalSysUnlock();
-
- usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
- buf, SERIAL_USB_BUFFERS_SIZE);
-
- osalSysLock();
- (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
+ usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
+ buf, SERIAL_USB_BUFFERS_SIZE);
}
}
}
@@ -179,12 +174,7 @@ static void obnotify(io_buffers_queue_t *bqp) {
uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n);
if (buf != NULL) {
/* Buffer found, starting a new transaction.*/
- osalSysUnlock();
-
- usbPrepareTransmit(sdup->config->usbp, sdup->config->bulk_in, buf, n);
-
- osalSysLock();
- (void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in);
+ usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
}
}
}
@@ -319,9 +309,8 @@ void sduConfigureHookI(SerialUSBDriver *sdup) {
osalDbgAssert(buf != NULL, "no free buffer");
- usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
- buf, SERIAL_USB_BUFFERS_SIZE);
- (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
+ usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
+ buf, SERIAL_USB_BUFFERS_SIZE);
}
/**
@@ -392,12 +381,7 @@ void sduSOFHookI(SerialUSBDriver *sdup) {
osalDbgAssert(buf != NULL, "queue is empty");
- osalSysUnlockFromISR();
-
- usbPrepareTransmit(sdup->config->usbp, sdup->config->bulk_in, buf, n);
-
- osalSysLockFromISR();
- (void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in);
+ usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
}
}
@@ -431,13 +415,10 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
/* Checking if there is a buffer ready for transmission.*/
buf = obqGetFullBufferI(&sdup->obqueue, &n);
- /* Unlocking the critical zone.*/
- osalSysUnlockFromISR();
-
if (buf != NULL) {
/* The endpoint cannot be busy, we are in the context of the callback,
so it is safe to transmit without a check.*/
- usbPrepareTransmit(usbp, ep, buf, n);
+ usbStartTransmitI(usbp, ep, buf, n);
}
else if ((usbp->epc[ep]->in_state->txsize > 0U) &&
((usbp->epc[ep]->in_state->txsize &
@@ -446,17 +427,13 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
size. Otherwise the recipient may expect more data coming soon and
not return buffered data to app. See section 5.8.3 Bulk Transfer
Packet Size Constraints of the USB Specification document.*/
- usbPrepareTransmit(usbp, ep, usbp->setup, 0);
+ usbStartTransmitI(usbp, ep, usbp->setup, 0);
}
else {
/* Nothing to transmit.*/
- return;
}
- /* Locking again and starting transmission.*/
- osalSysLockFromISR();
- (void) usbStartTransmitI(usbp, ep);
osalSysUnlockFromISR();
}
@@ -483,7 +460,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
/* Posting the filled buffer in the queue.*/
ibqPostFullBufferI(&sdup->ibqueue,
- usbGetReceiveTransactionSizeI(sdup->config->usbp,
+ usbGetReceiveTransactionSizeX(sdup->config->usbp,
sdup->config->bulk_out));
/* The endpoint cannot be busy, we are in the context of the callback,
@@ -492,11 +469,8 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
buf = ibqGetEmptyBufferI(&sdup->ibqueue);
if (buf != NULL) {
/* Buffer found, starting a new transaction.*/
- osalSysUnlockFromISR();
- usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
- buf, SERIAL_USB_BUFFERS_SIZE);
- osalSysLockFromISR();
- (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
+ usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
+ buf, SERIAL_USB_BUFFERS_SIZE);
}
osalSysUnlockFromISR();
}
diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c
index b6813c381..4f52424fb 100644
--- a/os/hal/src/usb.c
+++ b/os/hal/src/usb.c
@@ -401,22 +401,31 @@ void usbDisableEndpointsI(USBDriver *usbp) {
}
/**
- * @brief Prepares for a receive transaction on an OUT endpoint.
- * @post The endpoint is ready for @p usbStartReceiveI().
- * @note This function can be called both in ISR and thread context.
+ * @brief Starts a receive transaction on an OUT endpoint.
+ * @note This function is meant to be called from ISR context outside
+ * critical zones because there is a potentially slow operation
+ * inside.
*
* @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
+ * @param[in] n transaction size. It is recommended a multiple of
+ * the packet size because the excess is discarded.
*
- * @special
+ * @iclass
*/
-void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
+void usbStartReceiveI(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n) {
USBOutEndpointState *osp;
+ osalDbgCheckClassI();
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
+ osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving");
+
+ /* Marking the endpoint as active.*/
+ usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep);
+ /* Setting up the transfer.*/
osp = usbp->epc[ep]->out_state;
osp->rxbuf = buf;
osp->rxsize = n;
@@ -425,29 +434,35 @@ void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
osp->thread = NULL;
#endif
- usb_lld_prepare_receive(usbp, ep);
+ /* Starting transfer.*/
+ usb_lld_start_out(usbp, ep);
}
/**
- * @brief Prepares for a transmit transaction on an IN endpoint.
- * @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.
+ * @brief Starts a transmit transaction on an IN endpoint.
+ * @note This function is meant to be called from ISR context outside
+ * critical zones because there is a potentially slow operation
+ * inside.
*
* @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
+ * @iclass
*/
-void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
+void usbStartTransmitI(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n) {
USBInEndpointState *isp;
+ osalDbgCheckClassI();
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
+ osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting");
+
+ /* Marking the endpoint as active.*/
+ usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep);
+ /* Setting up the transfer.*/
isp = usbp->epc[ep]->in_state;
isp->txbuf = buf;
isp->txsize = n;
@@ -456,63 +471,8 @@ void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
isp->thread = NULL;
#endif
- 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.
- *
- * @iclass
- */
-bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
-
- osalDbgCheckClassI();
- osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
-
- if (usbGetReceiveStatusI(usbp, ep)) {
- return true;
- }
-
- usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep);
- usb_lld_start_out(usbp, ep);
- return false;
-}
-
-/**
- * @brief Starts a transmit transaction on an IN 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.
- *
- * @iclass
- */
-bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
-
- osalDbgCheckClassI();
- osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
-
- if (usbGetTransmitStatusI(usbp, ep)) {
- return true;
- }
-
- usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep);
+ /* Starting transfer.*/
usb_lld_start_in(usbp, ep);
- return false;
}
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
@@ -527,18 +487,23 @@ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
*
* @return The received effective data size, it can be less than
* the amount specified.
- * @retval MSG_RESET operation aborted by a reset.
- * @retval MSG_TIMEOUT operation aborted by a suspend.
+ * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
+ * has been aborted by an USB reset or a transition to
+ * the @p USB_SUSPENDED state.
*
* @api
*/
msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
msg_t msg;
- usbPrepareReceive(usbp, ep, buf, n);
-
osalSysLock();
- usbStartReceiveI(usbp, ep);
+
+ if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ osalSysUnlock();
+ return MSG_RESET;
+ }
+
+ usbStartReceiveI(usbp, ep, buf, n);
msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread);
osalSysUnlock();
@@ -555,18 +520,23 @@ msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
*
* @return The operation status.
* @retval MSG_OK operation performed successfully.
- * @retval MSG_RESET operation aborted by a reset.
- * @retval MSG_TIMEOUT operation aborted by a suspend.
+ * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
+ * has been aborted by an USB reset or a transition to
+ * the @p USB_SUSPENDED state.
*
* @api
*/
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) {
msg_t msg;
- usbPrepareTransmit(usbp, ep, buf, n);
-
osalSysLock();
- usbStartTransmitI(usbp, ep);
+
+ if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ osalSysUnlock();
+ return MSG_RESET;
+ }
+
+ usbStartTransmitI(usbp, ep, buf, n);
msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
osalSysUnlock();
@@ -700,10 +670,10 @@ void _usb_suspend(USBDriver *usbp) {
if (usbp->epc[i] != NULL) {
osalSysLockFromISR();
if (usbp->epc[i]->in_state != NULL) {
- osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_TIMEOUT);
+ osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
}
if (usbp->epc[i]->out_state != NULL) {
- osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_TIMEOUT);
+ osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
}
osalSysUnlockFromISR();
}
@@ -787,9 +757,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
if (usbp->ep0n != 0U) {
/* Starts the transmit phase.*/
usbp->ep0state = USB_EP0_TX;
- usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n);
osalSysLockFromISR();
- (void) usbStartTransmitI(usbp, 0);
+ usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n);
osalSysUnlockFromISR();
}
else {
@@ -797,9 +766,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
- usbPrepareReceive(usbp, 0, NULL, 0);
osalSysLockFromISR();
- (void) usbStartReceiveI(usbp, 0);
+ usbStartReceiveI(usbp, 0, NULL, 0);
osalSysUnlockFromISR();
#else
usb_lld_end_setup(usbp, ep);
@@ -811,9 +779,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
if (usbp->ep0n != 0U) {
/* Starts the receive phase.*/
usbp->ep0state = USB_EP0_RX;
- usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n);
osalSysLockFromISR();
- (void) usbStartReceiveI(usbp, 0);
+ usbStartReceiveI(usbp, 0, usbp->ep0next, usbp->ep0n);
osalSysUnlockFromISR();
}
else {
@@ -821,9 +788,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
- usbPrepareTransmit(usbp, 0, NULL, 0);
osalSysLockFromISR();
- (void) usbStartTransmitI(usbp, 0);
+ usbStartTransmitI(usbp, 0, NULL, 0);
osalSysUnlockFromISR();
#else
usb_lld_end_setup(usbp, ep);
@@ -854,9 +820,8 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
transmitted.*/
if ((usbp->ep0n < max) &&
((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) {
- usbPrepareTransmit(usbp, 0, NULL, 0);
osalSysLockFromISR();
- (void) usbStartTransmitI(usbp, 0);
+ usbStartTransmitI(usbp, 0, NULL, 0);
osalSysUnlockFromISR();
usbp->ep0state = USB_EP0_WAITING_TX0;
return;
@@ -866,9 +831,8 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
/* Transmit phase over, receiving the zero sized status packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
- usbPrepareReceive(usbp, 0, NULL, 0);
osalSysLockFromISR();
- (void) usbStartReceiveI(usbp, 0);
+ usbStartReceiveI(usbp, 0, NULL, 0);
osalSysUnlockFromISR();
#else
usb_lld_end_setup(usbp, ep);
@@ -919,9 +883,8 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
/* Receive phase over, sending the zero sized status packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
- usbPrepareTransmit(usbp, 0, NULL, 0);
osalSysLockFromISR();
- (void) usbStartTransmitI(usbp, 0);
+ usbStartTransmitI(usbp, 0, NULL, 0);
osalSysUnlockFromISR();
#else
usb_lld_end_setup(usbp, ep);
@@ -931,7 +894,7 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
/* Status packet received, it must be zero sized, invoking the callback
if defined.*/
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
- if (usbGetReceiveTransactionSizeI(usbp, 0) != 0U) {
+ if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) {
break;
}
#endif