Skip to content

Commit

Permalink
feat(host/msc): Add request sense feature
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-marcisovsky committed May 21, 2024
1 parent 39b78e0 commit a3a113f
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 13 deletions.
4 changes: 4 additions & 0 deletions host/class/msc/usb_host_msc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.1.3 (unreleased)

- Implemented request sense, to get sense data from USB device in case of an error

## 1.1.2

- Added support for ESP32-P4
Expand Down
101 changes: 88 additions & 13 deletions host/class/msc/usb_host_msc/src/msc_scsi_bot.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ static const char *TAG = "USB_MSC_SCSI";

#define CWB_FLAG_DIRECTION_IN (1<<7) // device -> host

/**
* @brief Sense keys list
*
* @see USB Mass Storage Class – UFI Command Specification, Revision 1.0
* Table 51 - Sense Keys, ASC/ASCQ Listing for All Commands (sorted by Key)
*
*/
typedef enum {
SENSE_WRITE_PROTECTED_MEDIA = 0x00072700,
} sense_key_t;

const char *const sense_codes_strings[] = {
"WRITE PROTECTED MEDIA"
};

/**
* @brief Command Block Wrapper structure
*
Expand Down Expand Up @@ -211,11 +226,13 @@ static uint32_t cbw_tag;

static esp_err_t check_csw(msc_csw_t *csw, uint32_t tag)
{
bool csw_ok = csw->signature == CSW_SIGNATURE && csw->tag == tag &&
csw->dataResidue == 0 && csw->status == 0;
const bool csw_ok = csw->signature == CSW_SIGNATURE && csw->tag == tag &&
csw->dataResidue == 0 && csw->status == 0;

if (!csw_ok) {
ESP_LOGD(TAG, "CSW failed: status %d", csw->status);
ESP_LOGV(TAG, "CSW failed: dCSWSignature = 0x%02lX, dCSWTag = 0x%02lX, dCSWDataResidue = 0x%02lX",
csw->signature, csw->tag, csw->dataResidue);
ESP_LOGD(TAG, "CSW failed: bCSWStatus 0x%02X", csw->status);
}

return csw_ok ? ESP_OK : ESP_FAIL;
Expand Down Expand Up @@ -273,6 +290,21 @@ esp_err_t bot_execute_command(msc_device_t *device, msc_cbw_t *cbw, void *data,
return check_csw(&csw, cbw->tag);
}

static void decode_sense_keys(cbw_sense_response_t *sense_response)
{
const uint32_t key = 0x00 << 24 |
(sense_response->sense_key << 16) |
(sense_response->sense_code << 8) |
sense_response->sense_code_qualifier;

// Only decode WRITE_PROTECTED_MEDIA sense key, other keys are not implemented
if (key == SENSE_WRITE_PROTECTED_MEDIA) {
ESP_LOGE(TAG, "Sense key: %s", sense_codes_strings[0]);
} else {
ESP_LOGE(TAG, "Sense key: refer to USB Mass Storage Class – UFI Command Specification (Table 51)");
}
}


esp_err_t scsi_cmd_read10(msc_host_device_handle_t dev,
uint8_t *data,
Expand All @@ -289,7 +321,13 @@ esp_err_t scsi_cmd_read10(msc_host_device_handle_t dev,
.length = __builtin_bswap16(num_sectors),
};

return bot_execute_command(device, &cbw.base, data, num_sectors * sector_size);
esp_err_t ret = bot_execute_command(device, &cbw.base, data, num_sectors * sector_size);

// In case of an error, get an error code
if (ret != ESP_OK) {
MSC_RETURN_ON_ERROR( scsi_cmd_sense(device, NULL));
}
return ret;
}

esp_err_t scsi_cmd_write10(msc_host_device_handle_t dev,
Expand All @@ -306,7 +344,13 @@ esp_err_t scsi_cmd_write10(msc_host_device_handle_t dev,
.length = __builtin_bswap16(num_sectors),
};

return bot_execute_command(device, &cbw.base, (void *)data, num_sectors * sector_size);
esp_err_t ret = bot_execute_command(device, &cbw.base, (void *)data, num_sectors * sector_size);

// In case of an error, get an error code
if (ret != ESP_OK) {
MSC_RETURN_ON_ERROR( scsi_cmd_sense(device, NULL));
}
return ret;
}

esp_err_t scsi_cmd_read_capacity(msc_host_device_handle_t dev, uint32_t *block_size, uint32_t *block_count)
Expand All @@ -319,12 +363,17 @@ esp_err_t scsi_cmd_read_capacity(msc_host_device_handle_t dev, uint32_t *block_s
.opcode = SCSI_CMD_READ_CAPACITY,
};

MSC_RETURN_ON_ERROR( bot_execute_command(device, &cbw.base, &response, sizeof(response)) );
esp_err_t ret = bot_execute_command(device, &cbw.base, &response, sizeof(response));

// In case of an error, get an error code
if (ret != ESP_OK) {
MSC_RETURN_ON_ERROR( scsi_cmd_sense(device, NULL));
}

*block_count = __builtin_bswap32(response.block_count);
*block_size = __builtin_bswap32(response.block_size);

return ESP_OK;
return ret;
}

esp_err_t scsi_cmd_unit_ready(msc_host_device_handle_t dev)
Expand All @@ -335,7 +384,13 @@ esp_err_t scsi_cmd_unit_ready(msc_host_device_handle_t dev)
.opcode = SCSI_CMD_TEST_UNIT_READY,
};

return bot_execute_command(device, &cbw.base, NULL, 0);
esp_err_t ret = bot_execute_command(device, &cbw.base, NULL, 0);

// In case of an error, get an error code
if (ret != ESP_OK) {
MSC_RETURN_ON_ERROR( scsi_cmd_sense(device, NULL));
}
return ret;
}

esp_err_t scsi_cmd_sense(msc_host_device_handle_t dev, scsi_sense_data_t *sense)
Expand All @@ -351,9 +406,11 @@ esp_err_t scsi_cmd_sense(msc_host_device_handle_t dev, scsi_sense_data_t *sense)

MSC_RETURN_ON_ERROR( bot_execute_command(device, &cbw.base, &response, sizeof(response)) );

if (sense->key) {
ESP_LOGD(TAG, "sense_key: 0x%02X, code: 0x%02X, qualifier: 0x%02X",
if (sense == NULL) {
ESP_LOGE(TAG, "sense_key: 0x%02X, code: 0x%02X, qualifier: 0x%02X",
response.sense_key, response.sense_code, response.sense_code_qualifier);
decode_sense_keys(&response);
return ESP_OK;
}

sense->key = response.sense_key;
Expand All @@ -374,7 +431,13 @@ esp_err_t scsi_cmd_inquiry(msc_host_device_handle_t dev)
.allocation_length = sizeof(response),
};

return bot_execute_command(device, &cbw.base, &response, sizeof(response) );
esp_err_t ret = bot_execute_command(device, &cbw.base, &response, sizeof(response) );

// In case of an error, get an error code
if (ret != ESP_OK) {
MSC_RETURN_ON_ERROR( scsi_cmd_sense(device, NULL));
}
return ret;
}

esp_err_t scsi_cmd_mode_sense(msc_host_device_handle_t dev)
Expand All @@ -389,7 +452,13 @@ esp_err_t scsi_cmd_mode_sense(msc_host_device_handle_t dev)
.parameter_list_length = sizeof(response),
};

return bot_execute_command(device, &cbw.base, &response, sizeof(response) );
esp_err_t ret = bot_execute_command(device, &cbw.base, &response, sizeof(response) );

// In case of an error, get an error code
if (ret != ESP_OK) {
MSC_RETURN_ON_ERROR( scsi_cmd_sense(device, NULL));
}
return ret;
}

esp_err_t scsi_cmd_prevent_removal(msc_host_device_handle_t dev, bool prevent)
Expand All @@ -401,5 +470,11 @@ esp_err_t scsi_cmd_prevent_removal(msc_host_device_handle_t dev, bool prevent)
.prevent = (uint8_t) prevent,
};

return bot_execute_command(device, &cbw.base, NULL, 0);
esp_err_t ret = bot_execute_command(device, &cbw.base, NULL, 0);

// In case of an error, get an error code
if (ret != ESP_OK) {
MSC_RETURN_ON_ERROR( scsi_cmd_sense(device, NULL));
}
return ret;
}

0 comments on commit a3a113f

Please sign in to comment.