35#define MSD_REQ_RESET   0xFF 
   36#define MSD_GET_MAX_LUN 0xFE 
   39#define MSD_CBW_SIGNATURE 0x43425355 
   40#define MSD_CSW_SIGNATURE 0x53425355 
   43#define MSD_SETUP_WORD(setup, index) (uint16_t)(((uint16_t)setup[index + 1] << 8) | (setup[index] & 0x00FF)) 
   44#define MSD_SETUP_VALUE(setup)       MSD_SETUP_WORD(setup, 2) 
   45#define MSD_SETUP_INDEX(setup)       MSD_SETUP_WORD(setup, 4) 
   46#define MSD_SETUP_LENGTH(setup)      MSD_SETUP_WORD(setup, 6) 
   49#define MSD_COMMAND_PASSED      0x00 
   50#define MSD_COMMAND_FAILED      0x01 
   51#define MSD_COMMAND_PHASE_ERROR 0x02 
   54#define SCSI_CMD_TEST_UNIT_READY              0x00 
   55#define SCSI_CMD_REQUEST_SENSE                0x03 
   56#define SCSI_CMD_FORMAT_UNIT                  0x04 
   57#define SCSI_CMD_INQUIRY                      0x12 
   58#define SCSI_CMD_MODE_SENSE_6                 0x1A 
   59#define SCSI_CMD_START_STOP_UNIT              0x1B 
   60#define SCSI_CMD_SEND_DIAGNOSTIC              0x1D 
   61#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E 
   62#define SCSI_CMD_READ_FORMAT_CAPACITIES       0x23 
   63#define SCSI_CMD_READ_CAPACITY_10             0x25 
   64#define SCSI_CMD_READ_10                      0x28 
   65#define SCSI_CMD_WRITE_10                     0x2A 
   66#define SCSI_CMD_VERIFY_10                    0x2F 
   69#define SCSI_SENSE_KEY_GOOD                            0x00 
   70#define SCSI_SENSE_KEY_RECOVERED_ERROR                 0x01 
   71#define SCSI_SENSE_KEY_NOT_READY                       0x02 
   72#define SCSI_SENSE_KEY_MEDIUM_ERROR                    0x03 
   73#define SCSI_SENSE_KEY_HARDWARE_ERROR                  0x04 
   74#define SCSI_SENSE_KEY_ILLEGAL_REQUEST                 0x05 
   75#define SCSI_SENSE_KEY_UNIT_ATTENTION                  0x06 
   76#define SCSI_SENSE_KEY_DATA_PROTECT                    0x07 
   77#define SCSI_SENSE_KEY_BLANK_CHECK                     0x08 
   78#define SCSI_SENSE_KEY_VENDOR_SPECIFIC                 0x09 
   79#define SCSI_SENSE_KEY_COPY_ABORTED                    0x0A 
   80#define SCSI_SENSE_KEY_ABORTED_COMMAND                 0x0B 
   81#define SCSI_SENSE_KEY_VOLUME_OVERFLOW                 0x0D 
   82#define SCSI_SENSE_KEY_MISCOMPARE                      0x0E 
   84#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION          0x00 
   85#define SCSI_ASENSE_WRITE_FAULT                        0x03 
   86#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY             0x04 
   87#define SCSI_ASENSE_READ_ERROR                         0x11 
   88#define SCSI_ASENSE_INVALID_COMMAND                    0x20 
   89#define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21 
   90#define SCSI_ASENSE_INVALID_FIELD_IN_CDB               0x24 
   91#define SCSI_ASENSE_WRITE_PROTECTED                    0x27 
   92#define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE          0x28 
   93#define SCSI_ASENSE_FORMAT_ERROR                       0x31 
   94#define SCSI_ASENSE_MEDIUM_NOT_PRESENT                 0x3A 
   96#define SCSI_ASENSEQ_NO_QUALIFIER                      0x00 
   97#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED             0x01 
   98#define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED     0x02 
   99#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS             0x07 
  142  DWORD v = ((
val << 8) & 0xFF00FF00) | ((
val >> 8) & 0xFF00FF);
 
  143  return ((v << 16) & 0xFFFF0000) | ((v >> 16) & 0x0000FFFF);
 
 
  151  return (((
val >> 8) & 0xff) | ((
val & 0xff) << 8));
 
 
  218    switch (usbp->setup[1]) {
 
 
  315  if (
msdp->bot_reset) {
 
  316    msdp->config->usbp->transmitting = 0;
 
 
  329  if (
msdp->bot_reset) {
 
  330    msdp->config->usbp->receiving = 0;
 
 
  341  msdp->sense.byte[2] = key;
 
 
  357  if (cbw->scsi_cmd_data[1] & 0x01) {
 
  360    switch (cbw->scsi_cmd_data[2]) {
 
 
  429  if (!(cbw->scsi_cmd_data[1] & (1 << 2))) {
 
  435    msdp->result = 
false;
 
 
  461    msdp->result = 
false;
 
  477    msdp->result = 
false;
 
  491    for (i = 0; i < 
total; i++) {
 
  493      if (i < (
total - 1)) {
 
  506        msdp->result = 
false;
 
  512      if (i < (
total - 1)) {
 
  529      msdp->result = 
false;
 
  536    for (i = 0; i < 
total; i++) {
 
  540      if (i < (
total - 1)) {
 
  549          msdp->result = 
false;
 
 
  573  if ((
msdp->cbw.scsi_cmd_data[4] & 0x03) == 0x02) {
 
 
  644    msdp->result = 
false;
 
 
  681      ((cbw->data_len > 0) && (cbw->flags & 0x1F)) ||
 
  682      (cbw->scsi_cmd_len == 0) ||
 
  683      (cbw->scsi_cmd_len > 16)) {
 
  697    msdp->result = 
false;
 
  710  switch (cbw->scsi_cmd_data[0]) {
 
  722      if (
msdp->config->rw_activity_callback) {
 
  723        msdp->config->rw_activity_callback(
true);
 
  726      if (
msdp->config->rw_activity_callback) {
 
  727        msdp->config->rw_activity_callback(
false);
 
  783  if (sleep & !
msdp->bot_reset) {
 
  789  if (!
msdp->result && cbw->data_len) {
 
  802  csw->data_residue = cbw->data_len;
 
 
  819  msdp->bot_reset = 
false;
 
  820  msdp->reconfigured_or_reset_event = 
false;
 
  835  for (i = 0; i < 
sizeof(
msdp->sense.byte); i++) {
 
  836    msdp->sense.byte[i] = 0x00;
 
  838  msdp->sense.byte[0] = 0x70; 
 
  839  msdp->sense.byte[7] = 0x0A; 
 
  842  msdp->inquiry.peripheral = 0x00;           
 
  843  msdp->inquiry.removable = 0x80;            
 
  844  msdp->inquiry.version = 0x04;              
 
  845  msdp->inquiry.response_data_format = 0x02; 
 
  846  msdp->inquiry.additional_length = 0x20;    
 
  847  msdp->inquiry.sccstp = 0x00;
 
  848  msdp->inquiry.bqueetc = 0x00;
 
  849  msdp->inquiry.cmdque = 0x00;
 
 
  867  for (i = 0; i < 
sizeof(
msdp->config->short_vendor_id); ++i) {
 
  868    msdp->inquiry.vendor_id[i] = 
config->short_vendor_id[i];
 
  870  for (i = 0; i < 
sizeof(
msdp->config->short_product_id); ++i) {
 
  871    msdp->inquiry.product_id[i] = 
config->short_product_id[i];
 
  873  for (i = 0; i < 
sizeof(
msdp->config->short_product_version); ++i) {
 
  874    msdp->inquiry.product_rev[i] = 
config->short_product_version[i];
 
 
  914  msdp->config->usbp->in_params[
msdp->config->bulk_ep] = 
NULL;
 
  915  msdp->config->usbp->out_params[
msdp->config->bulk_ep] = 
NULL;
 
 
 1056  'S', 0, 
'T', 0, 
'M', 0, 
'i', 0, 
'c', 0, 
'r', 0, 
'o', 0, 
'M', 0, 
'S', 0, 
'D', 0
 
 
 1067  'M', 0, 
'S', 0, 
'D', 0, 
' ', 0, 
'E', 0, 
'x', 0, 
'a', 0, 
'm', 0, 
'p', 0, 
'l', 0, 
'e', 0
 
 
 1078  '0', 0, 
'1', 0, 
'4', 0, 
'2', 0, 
'3', 0, 
'0', 0, 
'F', 0, 
'K', 0, 
'0', 0, 
'0', 0, 
'0', 0, 
'1', 0
 
 
 1172    if (
msdp->reconfigured_or_reset_event) {
 
 1175      msdp->reconfigured_or_reset_event = 
false;
 
 1188    switch (
msdp->state) {
 
 
Specific RAM section for DMA usage on F7.
#define IN_DMA_SECTION_CLEAR(var)
static const struct usb_config_descriptor config
Driver configuration structure.
usbep_t bulk_ep
Index of the USB endpoint to use for transfers.
USBDriver * usbp
USB driver to use for communication.
static USBMassStorageConfig msdConfig
static void msd_start_transmit(USBMassStorageDriver *msdp, const uint8_t *buffer, size_t size)
Starts sending data.
static const USBDescriptor productDescriptor
static const uint8_t vendorDescriptorData[]
#define SCSI_SENSE_KEY_GOOD
#define SCSI_CMD_READ_FORMAT_CAPACITIES
static THD_WORKING_AREA(mass_storage_thread_wa, 1024)
#define SCSI_CMD_START_STOP_UNIT
#define SCSI_CMD_SEND_DIAGNOSTIC
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION
#define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE
#define SCSI_CMD_READ_CAPACITY_10
bool msdRequestsHook(USBDriver *usbp)
Default requests hook.
static void usbEvent(USBDriver *usbp, usbevent_t event)
void debug_snd_evt_i(eventmask_t evt)
void debug_snd_evt_inl(eventmask_t evt)
#define MSD_COMMAND_PASSED
static const USBDescriptor languageDescriptor
void init_msd_driver(void *dbgThreadPtr, USBMassStorageConfig *msdConfig)
static DWORD swap_uint32(const DWORD val)
Byte-swap a 32 bits unsigned integer.
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB
#define SCSI_SENSE_KEY_RECOVERED_ERROR
static void msd_wait_for_isr(USBMassStorageDriver *msdp)
Wait until the end-point interrupt handler has been called.
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT
static void msd_handle_end_point_notification(USBDriver *usbp, usbep_t ep)
Called when data can be read or written on the endpoint – wakes the thread up.
static const USBDescriptor vendorDescriptor
static WORD swap_uint16(const WORD val)
Byte-swap a 16 bits unsigned integer.
bool msd_scsi_process_inquiry(USBMassStorageDriver *msdp)
Processes an INQUIRY SCSI command.
#define MSD_COMMAND_FAILED
static const USBDescriptor * getDescriptor(USBDriver *usbp, uint8_t type, uint8_t index, uint16_t lang)
#define SCSI_ASENSE_WRITE_PROTECTED
#define SCSI_SENSE_KEY_DATA_PROTECT
static const USBDescriptor serialNumberDescriptor
#define MSD_SETUP_INDEX(setup)
#define MSD_SETUP_LENGTH(setup)
#define SCSI_ASENSEQ_NO_QUALIFIER
#define MSD_CBW_SIGNATURE
static const USBDescriptor deviceDescriptor
#define MSD_CSW_SIGNATURE
bool msd_scsi_process_mode_sense_6(USBMassStorageDriver *msdp)
Processes a MODE_SENSE_6 SCSI command.
static USBMassStorageDriver UMSD
#define SCSI_SENSE_KEY_NOT_READY
void msdStart(USBMassStorageDriver *msdp, const USBMassStorageConfig *config)
Starts a USB mass storage driver.
bool msd_scsi_process_start_read_write_10(USBMassStorageDriver *msdp)
Processes a READ_WRITE_10 SCSI command.
#define SCSI_CMD_VERIFY_10
bool msd_scsi_process_read_capacity_10(USBMassStorageDriver *msdp)
Processes a READ_CAPACITY_10 SCSI command.
void msdInit(USBMassStorageDriver *msdp)
Initializse a USB mass storage driver.
void msdConfigureHookI(USBMassStorageDriver *msdp)
USB device configured handler.
#define SCSI_ASENSE_INVALID_COMMAND
void msd_register_evt_connected(event_listener_t *elp, eventmask_t mask)
register connected event source in local event mask
bool msd_scsi_process_start_stop_unit(USBMassStorageDriver *msdp)
Processes a START_STOP_UNIT SCSI command.
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST
void msd_register_evt_ejected(event_listener_t *elp, eventmask_t mask)
register ejected event source in local event mask
static void msd_scsi_set_sense(USBMassStorageDriver *msdp, uint8_t key, uint8_t acode, uint8_t aqual)
Changes the SCSI sense information.
static void msd_start_receive(USBMassStorageDriver *msdp, uint8_t *buffer, size_t size)
Starts receiving data.
static USBOutEndpointState ep1_out_state
OUT end-point 1 state.
bool msd_wait_for_command_block(USBMassStorageDriver *msdp)
Waits for a new command block.
static const USBDescriptor configurationDescriptor
#define MSD_SETUP_VALUE(setup)
static const uint8_t deviceDescriptorData[]
#define SCSI_CMD_TEST_UNIT_READY
static USBInEndpointState ep1_in_state
IN end-point 1 state.
void msdStop(USBMassStorageDriver *msdp)
Stops a USB mass storage driver.
static const uint8_t serialNumberDescriptorData[]
bool msd_read_command_block(USBMassStorageDriver *msdp)
Reads a newly received command block.
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL
#define SCSI_CMD_MODE_SENSE_6
#define SCSI_ASENSE_WRITE_FAULT
#define SCSI_CMD_FORMAT_UNIT
static const uint8_t languageDescriptorData[]
bool msd_scsi_process_read_format_capacities(USBMassStorageDriver *msdp)
Processes a READ_FORMAT_CAPACITIES SCSI command.
void debug_snd_evt_nl(eventmask_t evt)
#define SCSI_CMD_REQUEST_SENSE
#define SCSI_CMD_WRITE_10
#define SCSI_ASENSE_READ_ERROR
bool msd_scsi_process_test_unit_ready(USBMassStorageDriver *msdp)
Processes a TEST_UNIT_READY SCSI command.
static const USBEndpointConfig ep_data_config
End-point 1 initialization structure.
bool msd_scsi_process_request_sense(USBMassStorageDriver *msdp)
Processes a REQUEST_SENSE SCSI command.
bool msd_scsi_process_send_diagnostic(USBMassStorageDriver *msdp)
Processes a SEND_DIAGNOSTIC SCSI command.
static const uint8_t productDescriptorData[]
static const uint8_t configurationDescriptorData[]
#define SCSI_SENSE_KEY_MEDIUM_ERROR
void deinit_msd_driver(void)
static void mass_storage_thread(void *arg)
Mass storage thread that processes commands.
static const USBConfig usbConfig
#define EVT_SCSI_PROC_INQ
const USBMassStorageConfig * config
#define EVT_SCSI_REQ_TEST_UNIT_READY
bool reconfigured_or_reset_event
#define EVT_WAIT_FOR_COMMAND_BLOCK
#define EVT_SCSI_REQ_READ_CAP10
event_source_t evt_ejected
uint8_t capacity_list_length
#define PACK_STRUCT_BEGIN
#define EVT_SCSI_REQ_READ_FMT_CAP
#define EVT_SCSI_REQ_SENSE6
event_source_t evt_connected
#define EVT_SCSI_REQ_SENSE10
uint32_t desc_and_block_length
Response to a READ_CAPACITY_10 SCSI command.
USB mass storage driver structure.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.