diff --git a/os/hal/include/serial_usb.h b/os/hal/include/serial_usb.h index 104375391..25ce4859b 100644 --- a/os/hal/include/serial_usb.h +++ b/os/hal/include/serial_usb.h @@ -92,10 +92,6 @@ typedef struct { * @brief USB driver to use. */ USBDriver *usbp; - /** - * @brief USB driver configuration structure. - */ - USBConfig usb_config; } SerialUSBConfig; /** diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index fc082b56b..f05c341fc 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -223,7 +223,6 @@ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { config->usbp->param = sdup; sdup->state = SDU_READY; chSysUnlock(); - usbStart(config->usbp, &config->usb_config); } /** @@ -245,7 +244,6 @@ void sduStop(SerialUSBDriver *sdup) { "invalid state"); sdup->state = SDU_STOP; chSysUnlock(); - usbStop(sdup->config->usbp); } /** @@ -322,12 +320,23 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { so it is safe to transmit without a check.*/ chSysUnlockFromIsr(); - usbPrepareQueuedTransmit(usbp, - USB_CDC_DATA_REQUEST_EP, - &sdup->oqueue, n); + usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, n); chSysLockFromIsr(); - usbStartTransmitI(usbp, USB_CDC_DATA_REQUEST_EP); + usbStartTransmitI(usbp, ep); + } + else if (!(usbp->epc[ep]->in_state->txsize & + (usbp->epc[ep]->in_maxsize - 1))) { + /* Transmit zero sized packet in case the last one has maximum allowed + 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.*/ + chSysUnlockFromIsr(); + + usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, 0); + + chSysLockFromIsr(); + usbStartTransmitI(usbp, ep); } chSysUnlockFromIsr(); diff --git a/testhal/STM32F4xx/USB_CDC/main.c b/testhal/STM32F4xx/USB_CDC/main.c index 027f92a81..34bdf55eb 100644 --- a/testhal/STM32F4xx/USB_CDC/main.c +++ b/testhal/STM32F4xx/USB_CDC/main.c @@ -323,17 +323,21 @@ static void usb_event(USBDriver *usbp, usbevent_t event) { return; } +/* + * USB driver configuration. + */ +static const USBConfig usbcfg = { + usb_event, + get_descriptor, + sduRequestsHook, + NULL +}; + /* * Serial over USB driver configuration. */ static const SerialUSBConfig serusbcfg = { - &USBD1, - { - usb_event, - get_descriptor, - sduRequestsHook, - NULL - } + &USBD1 }; /*===========================================================================*/ @@ -479,13 +483,20 @@ int main(void) { halInit(); chSysInit(); + /* + * Initializes a serial-over-USB CDC driver. + */ + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + /* * Activates the USB driver and then the USB bus pull-up on D+. + * Note, a delay is inserted in order to not have to disconnect the cable + * after a reset. */ usbDisconnectBus(serusbcfg.usbp); chThdSleepMilliseconds(1000); - sduObjectInit(&SDU1); - sduStart(&SDU1, &serusbcfg); + usbStart(&USBD1, &usbcfg); usbConnectBus(serusbcfg.usbp); /*