aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.c4
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.h6
-rw-r--r--os/hal/src/usb.c43
3 files changed, 47 insertions, 6 deletions
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
index ab735b903..00ada1203 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
@@ -1005,7 +1005,7 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
/* OUT endpoint activation or deactivation.*/
otgp->oe[ep].DOEPTSIZ = 0;
- if (usbp->epc[ep]->out_maxsize != 0) {
+ if (usbp->epc[ep]->out_state != NULL) {
otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize);
otgp->DAINTMSK |= DAINTMSK_OEPM(ep);
}
@@ -1016,7 +1016,7 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
/* IN endpoint activation or deactivation.*/
otgp->ie[ep].DIEPTSIZ = 0;
- if (usbp->epc[ep]->in_maxsize != 0) {
+ if (usbp->epc[ep]->in_state != NULL) {
/* FIFO allocation for the IN endpoint.*/
fsize = usbp->epc[ep]->in_maxsize / 4;
if (usbp->epc[ep]->in_multiplier > 1)
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
index f59685c43..c90424c36 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
@@ -314,12 +314,14 @@ typedef struct {
uint16_t out_maxsize;
/**
* @brief @p USBEndpointState associated to the IN endpoint.
- * @details This structure maintains the state of the IN endpoint.
+ * @details This structure maintains the state of the IN endpoint,
+ * set to @p NULL if the IN endpoint is not used.
*/
USBInEndpointState *in_state;
/**
* @brief @p USBEndpointState associated to the OUT endpoint.
- * @details This structure maintains the state of the OUT endpoint.
+ * @details This structure maintains the state of the OUT endpoint,
+ * set to @p NULL if the OUT endpoint is not used.
*/
USBOutEndpointState *out_state;
/* End of the mandatory fields.*/
diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c
index 14d345b09..ce888e570 100644
--- a/os/hal/src/usb.c
+++ b/os/hal/src/usb.c
@@ -347,6 +347,14 @@ void usbInitEndpointI(USBDriver *usbp, usbep_t ep,
/* Logically enabling the endpoint in the USBDriver structure.*/
usbp->epc[ep] = epcp;
+ /* Clearing the state structures, custom fields as well.*/
+ if (epcp->in_state != NULL) {
+ memset(epcp->in_state, 0, sizeof(USBInEndpointState));
+ }
+ if (epcp->out_state != NULL) {
+ memset(epcp->out_state, 0, sizeof(USBOutEndpointState));
+ }
+
/* Low level endpoint activation.*/
usb_lld_init_endpoint(usbp, ep);
}
@@ -504,9 +512,10 @@ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
* @param[in] n transaction size. It is recommended a multiple of
* the packet size because the excess is discarded.
*
- * @return The received data effective size, it can be less than
+ * @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.
*
* @api
*/
@@ -534,6 +543,7 @@ 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.
*
* @api
*/
@@ -625,6 +635,17 @@ void _usb_reset(USBDriver *usbp) {
/* Invalidates all endpoints into the USBDriver structure.*/
for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
+#if USB_USE_WAIT == TRUE
+ /* Signaling the event to threads waiting on endpoints.*/
+ if (usbp->epc[i] != NULL) {
+ if (usbp->epc[i]->in_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
+ }
+ if (usbp->epc[i]->out_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
+ }
+ }
+#endif
usbp->epc[i] = NULL;
}
@@ -654,6 +675,24 @@ void _usb_suspend(USBDriver *usbp) {
/* Notification of suspend event.*/
_usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND);
+
+ /* Signaling the event to threads waiting on endpoints.*/
+#if USB_USE_WAIT == TRUE
+ {
+ unsigned i;
+
+ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
+ if (usbp->epc[i] != NULL) {
+ if (usbp->epc[i]->in_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_TIMEOUT);
+ }
+ if (usbp->epc[i]->out_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_TIMEOUT);
+ }
+ }
+ }
+ }
+#endif
}
/**
@@ -668,7 +707,7 @@ void _usb_suspend(USBDriver *usbp) {
void _usb_wakeup(USBDriver *usbp) {
/* State transition.*/
- usbp->state = USB_ACTIVE;
+ usbp->state = USB_ACTIVE;
/* Notification of suspend event.*/
_usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP);