Skip to content

Commit

Permalink
[squash] review points
Browse files Browse the repository at this point in the history
  • Loading branch information
tore-espressif committed Jun 2, 2023
1 parent f717265 commit 3a2a44f
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 103 deletions.
4 changes: 0 additions & 4 deletions usb/usb_host_msc/include/esp_private/msc_scsi_bot.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ esp_err_t scsi_cmd_prevent_removal(msc_host_device_handle_t device, bool prevent

esp_err_t scsi_cmd_mode_sense(msc_host_device_handle_t device);

esp_err_t msc_mass_reset(msc_host_device_handle_t device);

esp_err_t msc_get_max_lun(msc_host_device_handle_t device, uint8_t *lun);

#ifdef __cplusplus
}
#endif
12 changes: 12 additions & 0 deletions usb/usb_host_msc/include/usb/msc_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ esp_err_t msc_host_get_device_info(msc_host_device_handle_t device, msc_host_dev
*/
esp_err_t msc_host_print_descriptors(msc_host_device_handle_t device);

/**
* @brief MSC Bulk Only Transport Reset Recovery
*
* @see USB Mass Storage Class – Bulk Only Transport, Chapter 5.3.4
*
* @param[in] device Handle of MSC device
* @return
* - ESP_OK: The device was recovered from reset
* - ESP_FAI: Recovery unsuccessful, might indicate broken device
*/
esp_err_t msc_host_reset_recovery(msc_host_device_handle_t device);

#ifdef __cplusplus
}
#endif //__cplusplus
4 changes: 3 additions & 1 deletion usb/usb_host_msc/private_include/msc_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ esp_err_t msc_bulk_transfer(msc_device_t *device_handle, uint8_t *data, size_t s
* @param[in] ep Direction of the transfer
* @return esp_err_t
*/
esp_err_t msc_bulk_transfer_zero_cpy(msc_device_t *device_handle, uint8_t *data, size_t size, msc_endpoint_t ep);
esp_err_t msc_bulk_transfer_zcpy(msc_device_t *device_handle, uint8_t *data, size_t size, msc_endpoint_t ep);

/**
* @brief Trigger a CTRL transfer to device
Expand All @@ -82,6 +82,8 @@ esp_err_t msc_bulk_transfer_zero_cpy(msc_device_t *device_handle, uint8_t *data,
*/
esp_err_t msc_control_transfer(msc_device_t *device_handle, size_t len);

esp_err_t clear_feature(msc_device_t *device, uint8_t endpoint);

#define MSC_GOTO_ON_ERROR(exp) ESP_GOTO_ON_ERROR(exp, fail, TAG, "")

#define MSC_GOTO_ON_FALSE(exp, err) ESP_GOTO_ON_FALSE( (exp), err, fail, TAG, "" )
Expand Down
164 changes: 144 additions & 20 deletions usb/usb_host_msc/src/msc_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
#include "usb/usb_helpers.h"
#include "soc/soc_memory_layout.h"

// MSC driver spin lock
static portMUX_TYPE msc_lock = portMUX_INITIALIZER_UNLOCKED;

#define MSC_ENTER_CRITICAL() portENTER_CRITICAL(&msc_lock)
#define MSC_EXIT_CRITICAL() portEXIT_CRITICAL(&msc_lock)

Expand All @@ -46,6 +46,38 @@ static portMUX_TYPE msc_lock = portMUX_INITIALIZER_UNLOCKED;
} \
} while(0)

// MSC Control requests
#define USB_MASS_REQ_INIT_RESET(ctrl_req_ptr, intf_num) ({ \
(ctrl_req_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | \
USB_BM_REQUEST_TYPE_TYPE_CLASS | \
USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \
(ctrl_req_ptr)->bRequest = 0xFF; \
(ctrl_req_ptr)->wValue = 0; \
(ctrl_req_ptr)->wIndex = (intf_num); \
(ctrl_req_ptr)->wLength = 0; \
})

#define USB_MASS_REQ_INIT_GET_MAX_LUN(ctrl_req_ptr, intf_num) ({ \
(ctrl_req_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | \
USB_BM_REQUEST_TYPE_TYPE_CLASS | \
USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \
(ctrl_req_ptr)->bRequest = 0xFE; \
(ctrl_req_ptr)->wValue = 0; \
(ctrl_req_ptr)->wIndex = (intf_num); \
(ctrl_req_ptr)->wLength = 1; \
})

#define FEATURE_SELECTOR_ENDPOINT 0
#define USB_SETUP_PACKET_INIT_CLEAR_FEATURE_EP(ctrl_req_ptr, ep_num) ({ \
(ctrl_req_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | \
USB_BM_REQUEST_TYPE_TYPE_STANDARD | \
USB_BM_REQUEST_TYPE_RECIP_ENDPOINT; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_CLEAR_FEATURE; \
(ctrl_req_ptr)->wValue = FEATURE_SELECTOR_ENDPOINT; \
(ctrl_req_ptr)->wIndex = (ep_num); \
(ctrl_req_ptr)->wLength = 0; \
})

#define DEFAULT_XFER_SIZE (64) // Transfer size used for all transfers apart from SCSI read/write
#define WAIT_FOR_READY_TIMEOUT_MS 3000
#define SCSI_COMMAND_SET 0x06
Expand Down Expand Up @@ -104,6 +136,73 @@ static const usb_intf_desc_t *find_msc_interface(const usb_config_desc_t *config
return NULL;
}

esp_err_t clear_feature(msc_device_t *device, uint8_t endpoint)
{
usb_device_handle_t dev = device->handle;
usb_transfer_t *xfer = device->xfer;

esp_err_t err = usb_host_endpoint_flush(dev, endpoint);
if (ESP_OK != err ) {
// The endpoint cannot be flushed if it does not have STALL condition
// Return without ESP_LOGE
return err;
}
MSC_RETURN_ON_ERROR( usb_host_endpoint_clear(dev, endpoint) );

USB_SETUP_PACKET_INIT_CLEAR_FEATURE_EP((usb_setup_packet_t *)xfer->data_buffer, endpoint);
MSC_RETURN_ON_ERROR( msc_control_transfer(device, USB_SETUP_PACKET_SIZE) );

return ESP_OK;
}

/**
* @brief Bulk-Only Mass Storage Reset
*
* This class-specific request shall ready the device for the next CBW from the host.
* The device shall preserve the value of its bulk data toggle bits and endpoint STALL conditions despite the Bulk-Only Mass Storage Reset.
*
* @see USB Mass Storage Class – Bulk Only Transport, Chapter 3.1
*
* @param[in] dev MSC device handle
* @return esp_err_t
*/
static esp_err_t msc_mass_reset(msc_host_device_handle_t dev)
{
msc_device_t *device = (msc_device_t *)dev;
usb_transfer_t *xfer = device->xfer;

USB_MASS_REQ_INIT_RESET((usb_setup_packet_t *)xfer->data_buffer, device->config.iface_num);
MSC_RETURN_ON_ERROR( msc_control_transfer(device, USB_SETUP_PACKET_SIZE) );

return ESP_OK;
}

/**
* @brief MSC get maximum Logical Unit Number
*
* If the device implements 3 LUNs, the returned value is 2. (LUN0, LUN1, LUN2).
*
* This driver does not support multiple LUNs yet.
*
* @see USB Mass Storage Class – Bulk Only Transport, Chapter 3.2
*
* @param[in] dev MSC device handle
* @param[out] lun Maximum Logical Unit Number
* @return esp_err_t
*/
__attribute__((unused)) static esp_err_t msc_get_max_lun(msc_host_device_handle_t dev, uint8_t *lun)
{
msc_device_t *device = (msc_device_t *)dev;
usb_transfer_t *xfer = device->xfer;

USB_MASS_REQ_INIT_GET_MAX_LUN((usb_setup_packet_t *)xfer->data_buffer, device->config.iface_num);
MSC_RETURN_ON_ERROR( msc_control_transfer(device, USB_SETUP_PACKET_SIZE + 1) );

*lun = xfer->data_buffer[USB_SETUP_PACKET_SIZE];

return ESP_OK;
}

/**
* @brief Extracts configuration from configuration descriptor.
*
Expand Down Expand Up @@ -236,15 +335,19 @@ static void event_handler_task(void *arg)

static msc_device_t *find_msc_device(usb_device_handle_t device_handle)
{
msc_host_device_handle_t device;
msc_device_t *iter;
msc_device_t *device_found = NULL;

STAILQ_FOREACH(device, &s_msc_driver->devices_tailq, tailq_entry) {
if (device_handle == device->handle) {
return device;
MSC_ENTER_CRITICAL();
STAILQ_FOREACH(iter, &s_msc_driver->devices_tailq, tailq_entry) {
if (device_handle == iter->handle) {
device_found = iter;
break;
}
}
MSC_EXIT_CRITICAL();

return NULL;
return device_found;
}

static void client_event_cb(const usb_host_client_event_msg_t *event, void *arg)
Expand Down Expand Up @@ -459,21 +562,23 @@ static void transfer_callback(usb_transfer_t *transfer)
static usb_transfer_status_t wait_for_transfer_done(usb_transfer_t *xfer)
{
msc_device_t *device = (msc_device_t *)xfer->context;
usb_transfer_status_t status = xfer->status;
BaseType_t received = xSemaphoreTake(device->transfer_done, pdMS_TO_TICKS(xfer->timeout_ms));
usb_transfer_status_t status = xfer->status;

if (received != pdTRUE) {
usb_host_endpoint_halt(xfer->device_handle, xfer->bEndpointAddress);
usb_host_endpoint_flush(xfer->device_handle, xfer->bEndpointAddress);
xSemaphoreTake(device->transfer_done, portMAX_DELAY);
return USB_TRANSFER_STATUS_TIMED_OUT;
usb_host_endpoint_clear(xfer->device_handle, xfer->bEndpointAddress);
xSemaphoreTake(device->transfer_done, portMAX_DELAY); // Since we flushed the EP, this should return immediately
status = USB_TRANSFER_STATUS_TIMED_OUT;
}

return status;
}

esp_err_t msc_bulk_transfer(msc_device_t *device, uint8_t *data, size_t size, msc_endpoint_t ep)
{
esp_err_t ret;
usb_transfer_t *xfer = device->xfer;
MSC_RETURN_ON_FALSE(size <= xfer->data_buffer_size, ESP_ERR_INVALID_SIZE);
uint8_t endpoint = (ep == MSC_EP_IN) ? device->config.bulk_in_ep : device->config.bulk_out_ep;
Expand All @@ -492,21 +597,24 @@ esp_err_t msc_bulk_transfer(msc_device_t *device, uint8_t *data, size_t size, ms
xfer->context = device;

MSC_RETURN_ON_ERROR( usb_host_transfer_submit(xfer) );
if (USB_TRANSFER_STATUS_COMPLETED != wait_for_transfer_done(xfer)) {
if (USB_TRANSFER_STATUS_STALL == wait_for_transfer_done(xfer)) {
return ESP_ERR_MSC_STALL;
}
return ESP_ERR_MSC_INTERNAL;
const usb_transfer_status_t status = wait_for_transfer_done(xfer);
switch (status) {
case USB_TRANSFER_STATUS_COMPLETED:
ret = ESP_OK; break;
case USB_TRANSFER_STATUS_STALL:
ret = ESP_ERR_MSC_STALL; break;
default:
ret = ESP_ERR_MSC_INTERNAL; break;
}

if (is_in_endpoint(endpoint)) {
if (is_in_endpoint(endpoint) && (ESP_OK == ret)) {
memcpy(data, xfer->data_buffer, size);
}

return ESP_OK;
return ret;
}

esp_err_t msc_bulk_transfer_zero_cpy(msc_device_t *device, uint8_t *data, size_t size, msc_endpoint_t ep)
esp_err_t msc_bulk_transfer_zcpy(msc_device_t *device, uint8_t *data, size_t size, msc_endpoint_t ep)
{
esp_err_t ret = ESP_OK;
MSC_RETURN_ON_FALSE(esp_ptr_dma_capable(data), ESP_FAIL); // The passed buffer must be DMA capable
Expand Down Expand Up @@ -536,10 +644,16 @@ esp_err_t msc_bulk_transfer_zero_cpy(msc_device_t *device, uint8_t *data, size_t
xfer->context = device;

MSC_GOTO_ON_ERROR( usb_host_transfer_submit(xfer) );
if (USB_TRANSFER_STATUS_COMPLETED != wait_for_transfer_done(xfer)) {
MSC_GOTO_ON_FALSE(!(USB_TRANSFER_STATUS_STALL == wait_for_transfer_done(xfer)), ESP_ERR_MSC_STALL);
ret = ESP_ERR_MSC_INTERNAL;
const usb_transfer_status_t status = wait_for_transfer_done(xfer);
switch (status) {
case USB_TRANSFER_STATUS_COMPLETED:
ret = ESP_OK; break;
case USB_TRANSFER_STATUS_STALL:
ret = ESP_ERR_MSC_STALL; break;
default:
ret = ESP_ERR_MSC_INTERNAL; break;
}

fail:
*ptr = backup_buffer;
*siz = backup_size;
Expand All @@ -559,3 +673,13 @@ esp_err_t msc_control_transfer(msc_device_t *device, size_t len)
MSC_RETURN_ON_ERROR( usb_host_transfer_submit_control(s_msc_driver->client_handle, xfer));
return wait_for_transfer_done(xfer) == USB_TRANSFER_STATUS_COMPLETED ? ESP_OK : ESP_ERR_MSC_INTERNAL;
}

esp_err_t msc_host_reset_recovery(msc_host_device_handle_t device)
{
// Clear feature will fail if there is not STALL on the endpoint, so we don't check the errors here
clear_feature(device, device->config.bulk_in_ep);
clear_feature(device, device->config.bulk_out_ep);
ESP_RETURN_ON_ERROR( msc_mass_reset(device), TAG, "Mass reset failed" );
MSC_RETURN_ON_ERROR( msc_wait_for_ready_state(device, WAIT_FOR_READY_TIMEOUT_MS) );
return ESP_OK;
}
Loading

0 comments on commit 3a2a44f

Please sign in to comment.