diff --git a/usb/device/USBDevice/USBDevice.cpp b/usb/device/USBDevice/USBDevice.cpp index 84910903e2..808def213c 100644 --- a/usb/device/USBDevice/USBDevice.cpp +++ b/usb/device/USBDevice/USBDevice.cpp @@ -200,7 +200,7 @@ bool USBDevice::_control_out() } /* Read from endpoint */ - packetSize = _phy->ep0_read_result(_transfer.ptr, _transfer.remaining); + packetSize = _phy->ep0_read_result(); /* Check if transfer size is valid */ if (packetSize > _transfer.remaining) { @@ -224,7 +224,7 @@ bool USBDevice::_control_out() complete_request_xfer_done(true); } } else { - _phy->ep0_read(); + _phy->ep0_read(_transfer.ptr, _transfer.remaining); } return true; @@ -330,7 +330,7 @@ void USBDevice::_complete_request_xfer_done() _phy->ep0_write(NULL, 0); } else if (_transfer.stage == DataIn) { _transfer.stage = Status; - _phy->ep0_read(); + _phy->ep0_read(NULL, 0); } } @@ -800,7 +800,7 @@ void USBDevice::_control_setup_continue() } else { /* OUT stage */ _transfer.stage = DataOut; - _phy->ep0_read(); + _phy->ep0_read(_transfer.ptr, _transfer.remaining); } } else { /* Status stage */ @@ -1052,11 +1052,6 @@ bool USBDevice::endpoint_add(usb_ep_t endpoint, uint32_t max_packet_size, usb_ep info->flags |= ENDPOINT_ENABLED; info->pending = 0; info->max_packet_size = max_packet_size; - ret = _phy->endpoint_read(endpoint, max_packet_size); - if (!ret) { - MBED_ASSERT(0); - endpoint_remove(endpoint); - } } unlock(); @@ -1261,7 +1256,7 @@ uint32_t USBDevice::endpoint_max_packet_size(usb_ep_t endpoint) return size; } -bool USBDevice::read(usb_ep_t endpoint, uint8_t *buffer, uint32_t max_size, uint32_t *size) +bool USBDevice::read_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t max_size) { lock(); @@ -1291,17 +1286,43 @@ bool USBDevice::read(usb_ep_t endpoint, uint8_t *buffer, uint32_t max_size, uint return false; } - bool ret = _phy->endpoint_read_result(endpoint, buffer, max_size, size); - if (ret) { - info->pending -= 1; - _phy->endpoint_read(endpoint, info->max_packet_size); - } + _phy->endpoint_read(endpoint, buffer, info->max_packet_size); unlock(); - return ret; + + return true; } -bool USBDevice::write(usb_ep_t endpoint, uint8_t *buffer, uint32_t size) +uint32_t USBDevice::read_finish(usb_ep_t endpoint) +{ + lock(); + + if (!EP_INDEXABLE(endpoint)) { + MBED_ASSERT(0); + unlock(); + return 0; + } + + if (!configured()) { + unlock(); + return 0; + } + + endpoint_info_t *info = &_endpoint_info[EP_TO_INDEX(endpoint)]; + if (!(info->flags & ENDPOINT_ENABLED)) { + // Invalid endpoint is being used + MBED_ASSERT(0); + unlock(); + return 0; + } + + uint32_t size = 0; + size = _phy->endpoint_read_result(endpoint); + unlock(); + return size; +} + +bool USBDevice::write_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size) { lock(); @@ -1341,13 +1362,47 @@ bool USBDevice::write(usb_ep_t endpoint, uint8_t *buffer, uint32_t size) /* Send report */ bool ret = _phy->endpoint_write(endpoint, buffer, size); if (ret) { + info->transfer_size = size; info->pending += 1; + } else { + info->transfer_size = 0; } unlock(); return ret; } +uint32_t USBDevice::write_finish(usb_ep_t endpoint) +{ + uint32_t ret = 0; + + lock(); + + if (!EP_INDEXABLE(endpoint)) { + MBED_ASSERT(0); + unlock(); + return false; + } + + if (!configured()) { + unlock(); + return false; + } + + endpoint_info_t *info = &_endpoint_info[EP_TO_INDEX(endpoint)]; + if (!(info->flags & ENDPOINT_ENABLED)) { + // Invalid endpoint is being used + MBED_ASSERT(0); + unlock(); + return 0; + } + + ret = info->transfer_size; + + unlock(); + return ret; +} + const uint8_t *USBDevice::device_desc() { uint8_t device_descriptor_temp[] = { diff --git a/usb/device/USBDevice/USBDevice.h b/usb/device/USBDevice/USBDevice.h index 9d3e01d4df..a61549ca68 100644 --- a/usb/device/USBDevice/USBDevice.h +++ b/usb/device/USBDevice/USBDevice.h @@ -202,26 +202,33 @@ public: uint32_t endpoint_max_packet_size(usb_ep_t endpoint); /** - * Read a packet on the given endpoint + * start a read on the given endpoint * - * Get the contents of an IN transfer. To ensure all the data from this - * endpoint is read make sure the buffer and size passed in is at least - * as big as the maximum packet for this endpoint. + * Start a read on the given endpoint. The data buffer must remain + * unchanged until the transfer either completes or is aborted. * * @param endpoint endpoint to read data from * @param buffer buffer to fill with read data - * @param max_size the total size of the data buffer. This must be at least - * the max packet size of this endpoint - * @param size The size of data that was read + * @param size The size of data to read. This must be greater than or equal + * to the max packet size for this endpoint * @return true if the read was completed, otherwise false * @note This endpoint must already have been setup with endpoint_add */ - bool read(usb_ep_t endpoint, uint8_t *buffer, uint32_t max_size, uint32_t *size); + bool read_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size); + + /** + * Get the status of a read + * + * @param endpoint endpoint to get the status of + * @return number of bytes read by this endpoint + */ + uint32_t read_finish(usb_ep_t endpoint); /** * Write a data to the given endpoint * - * Write data to an endpoint. + * Write data to an endpoint. The data sent must remain unchanged until + * the transfer either completes or is aborted. * * @param endpoint endpoint to write data to * @param buffer data to write @@ -229,7 +236,15 @@ public: * max packet size of this endpoint * @note This endpoint must already have been setup with endpoint_add */ - bool write(usb_ep_t endpoint, uint8_t *buffer, uint32_t size); + bool write_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size); + + /** + * Get the status of a write + * + * @param endpoint endpoint to get the status of + * @return number of bytes sent by this endpoint + */ + uint32_t write_finish(usb_ep_t endpoint); /* * Get device descriptor. @@ -519,6 +534,7 @@ private: struct endpoint_info_t { void (USBDevice::*callback)(usb_ep_t endpoint); uint16_t max_packet_size; + uint16_t transfer_size; uint8_t flags; uint8_t pending; };