tinyusb/src/class/msc/msc_device.c
int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t bufsize)
{
  (void) bufsize; // TODO refractor later
  int32_t ret;

  switch ( p_cbw->command[0] )
  {
    case SCSI_CMD_READ_CAPACITY_10:
    {
      scsi_read_capacity10_resp_t read_capa10;

      uint32_t block_count;
      uint32_t block_size;
      uint16_t block_size_u16;

      tud_msc_capacity_cb(p_cbw->lun, &block_count, &block_size_u16);
      block_size = (uint32_t) block_size_u16;

      read_capa10.last_lba = ENDIAN_BE(block_count-1);
      read_capa10.block_size = ENDIAN_BE(block_size);

      ret = sizeof(read_capa10);
      memcpy(buffer, &read_capa10, ret);
    }
    break;

    case SCSI_CMD_READ_FORMAT_CAPACITY:
    {
      scsi_read_format_capacity_data_t read_fmt_capa =
      {
          .list_length     = 8,
          .block_num       = 0,
          .descriptor_type = 2, // formatted media
          .block_size_u16  = 0
      };

      uint32_t block_count;
      uint16_t block_size;

      tud_msc_capacity_cb(p_cbw->lun, &block_count, &block_size);
      read_fmt_capa.block_num = ENDIAN_BE(block_count);
      read_fmt_capa.block_size_u16 = ENDIAN_BE16(block_size);

      ret = sizeof(read_fmt_capa);
      memcpy(buffer, &read_fmt_capa, ret);
    }
    break;

    case SCSI_CMD_INQUIRY:
    {
      scsi_inquiry_resp_t inquiry_rsp =
      {
          .is_removable         = 1,
          .version              = 2,
          .response_data_format = 2,
          .vendor_id            = "Adafruit",
          .product_id           = "Feather52840",
          .product_rev          = "1.0"
      };

      strncpy((char*) inquiry_rsp.vendor_id  , CFG_TUD_MSC_VENDOR     , sizeof(inquiry_rsp.vendor_id));
      strncpy((char*) inquiry_rsp.product_id , CFG_TUD_MSC_PRODUCT    , sizeof(inquiry_rsp.product_id));
      strncpy((char*) inquiry_rsp.product_rev, CFG_TUD_MSC_PRODUCT_REV, sizeof(inquiry_rsp.product_rev));

      ret = sizeof(inquiry_rsp);
      memcpy(buffer, &inquiry_rsp, ret);
    }
    break;

    case SCSI_CMD_MODE_SENSE_6:
    {
      scsi_mode_sense6_resp_t mode_resp =
      {
          .data_len = 3,
          .medium_type = 0,
          .write_protected = false,
          .reserved = 0,
          .block_descriptor_len = 0  // no block descriptor are included
      };

      bool writable = true;
      if (tud_msc_is_writable_cb) {
          writable = tud_msc_is_writable_cb(p_cbw->lun);
      }
      mode_resp.write_protected = !writable;

      ret = sizeof(mode_resp);
      memcpy(buffer, &mode_resp, ret);
    }
    break;

    case SCSI_CMD_REQUEST_SENSE:
    {
      scsi_sense_fixed_resp_t sense_rsp =
      {
          .response_code = 0x70,
          .valid         = 1
      };

      sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;

      sense_rsp.sense_key           = _mscd_itf.sense_key;
      sense_rsp.add_sense_code      = _mscd_itf.add_sense_code;
      sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier;

      ret = sizeof(sense_rsp);
      memcpy(buffer, &sense_rsp, ret);

      // Clear sense data after copy
      tud_msc_set_sense(p_cbw->lun, 0, 0, 0);
    }
    break;

    default: ret = -1; break;
  }

  return ret;
}
// return length of response (copied to buffer), -1 if it is not an built-in commands

return length of response (copied to buffer), -1 if it is not an built-in commands
return length of response ( copied to buffer ) - 1 if it is not an built - in commands
int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t bufsize)
{
  (void) bufsize; 
  int32_t ret;
  switch ( p_cbw->command[0] )
  {
    case SCSI_CMD_READ_CAPACITY_10:
    {
      scsi_read_capacity10_resp_t read_capa10;
      uint32_t block_count;
      uint32_t block_size;
      uint16_t block_size_u16;
      tud_msc_capacity_cb(p_cbw->lun, &block_count, &block_size_u16);
      block_size = (uint32_t) block_size_u16;
      read_capa10.last_lba = ENDIAN_BE(block_count-1);
      read_capa10.block_size = ENDIAN_BE(block_size);
      ret = sizeof(read_capa10);
      memcpy(buffer, &read_capa10, ret);
    }
    break;
    case SCSI_CMD_READ_FORMAT_CAPACITY:
    {
      scsi_read_format_capacity_data_t read_fmt_capa =
      {
          .list_length     = 8,
          .block_num       = 0,
          .descriptor_type = 2, 
          .block_size_u16  = 0
      };
      uint32_t block_count;
      uint16_t block_size;
      tud_msc_capacity_cb(p_cbw->lun, &block_count, &block_size);
      read_fmt_capa.block_num = ENDIAN_BE(block_count);
      read_fmt_capa.block_size_u16 = ENDIAN_BE16(block_size);
      ret = sizeof(read_fmt_capa);
      memcpy(buffer, &read_fmt_capa, ret);
    }
    break;
    case SCSI_CMD_INQUIRY:
    {
      scsi_inquiry_resp_t inquiry_rsp =
      {
          .is_removable         = 1,
          .version              = 2,
          .response_data_format = 2,
          .vendor_id            = "Adafruit",
          .product_id           = "Feather52840",
          .product_rev          = "1.0"
      };
      strncpy((char*) inquiry_rsp.vendor_id  , CFG_TUD_MSC_VENDOR     , sizeof(inquiry_rsp.vendor_id));
      strncpy((char*) inquiry_rsp.product_id , CFG_TUD_MSC_PRODUCT    , sizeof(inquiry_rsp.product_id));
      strncpy((char*) inquiry_rsp.product_rev, CFG_TUD_MSC_PRODUCT_REV, sizeof(inquiry_rsp.product_rev));
      ret = sizeof(inquiry_rsp);
      memcpy(buffer, &inquiry_rsp, ret);
    }
    break;
    case SCSI_CMD_MODE_SENSE_6:
    {
      scsi_mode_sense6_resp_t mode_resp =
      {
          .data_len = 3,
          .medium_type = 0,
          .write_protected = false,
          .reserved = 0,
          .block_descriptor_len = 0  
      };
      bool writable = true;
      if (tud_msc_is_writable_cb) {
          writable = tud_msc_is_writable_cb(p_cbw->lun);
      }
      mode_resp.write_protected = !writable;
      ret = sizeof(mode_resp);
      memcpy(buffer, &mode_resp, ret);
    }
    break;
    case SCSI_CMD_REQUEST_SENSE:
    {
      scsi_sense_fixed_resp_t sense_rsp =
      {
          .response_code = 0x70,
          .valid         = 1
      };
      sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
      sense_rsp.sense_key           = _mscd_itf.sense_key;
      sense_rsp.add_sense_code      = _mscd_itf.add_sense_code;
      sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier;
      ret = sizeof(sense_rsp);
      memcpy(buffer, &sense_rsp, ret);
      tud_msc_set_sense(p_cbw->lun, 0, 0, 0);
    }
    break;
    default: ret = -1; break;
  }
  return ret;
}
int32_t proc_builtin_scsi ( msc_cbw_t const * p_cbw , uint8_t * buffer , uint32_t bufsize ) { ( void ) bufsize ; int32_t ret ; switch ( p_cbw -> command [ 0 ] ) { case SCSI_CMD_READ_CAPACITY_10 : { scsi_read_capacity10_resp_t read_capa10 ; uint32_t block_count ; uint32_t block_size ; uint16_t block_size_u16 ; tud_msc_capacity_cb ( p_cbw -> lun , & block_count , & block_size_u16 ) ; block_size = ( uint32_t ) block_size_u16 ; read_capa10 . last_lba = ENDIAN_BE ( block_count - 1 ) ; read_capa10 . block_size = ENDIAN_BE ( block_size ) ; ret = sizeof ( read_capa10 ) ; memcpy ( buffer , & read_capa10 , ret ) ; } break ; case SCSI_CMD_READ_FORMAT_CAPACITY : { scsi_read_format_capacity_data_t read_fmt_capa = { . list_length = 8 , . block_num = 0 , . descriptor_type = 2 , . block_size_u16 = 0 } ; uint32_t block_count ; uint16_t block_size ; tud_msc_capacity_cb ( p_cbw -> lun , & block_count , & block_size ) ; read_fmt_capa . block_num = ENDIAN_BE ( block_count ) ; read_fmt_capa . block_size_u16 = ENDIAN_BE16 ( block_size ) ; ret = sizeof ( read_fmt_capa ) ; memcpy ( buffer , & read_fmt_capa , ret ) ; } break ; case SCSI_CMD_INQUIRY : { scsi_inquiry_resp_t inquiry_rsp = { . is_removable = 1 , . version = 2 , . response_data_format = 2 , . vendor_id = " " , . product_id = " " , . product_rev = " " } ; strncpy ( ( char * ) inquiry_rsp . vendor_id , CFG_TUD_MSC_VENDOR , sizeof ( inquiry_rsp . vendor_id ) ) ; strncpy ( ( char * ) inquiry_rsp . product_id , CFG_TUD_MSC_PRODUCT , sizeof ( inquiry_rsp . product_id ) ) ; strncpy ( ( char * ) inquiry_rsp . product_rev , CFG_TUD_MSC_PRODUCT_REV , sizeof ( inquiry_rsp . product_rev ) ) ; ret = sizeof ( inquiry_rsp ) ; memcpy ( buffer , & inquiry_rsp , ret ) ; } break ; case SCSI_CMD_MODE_SENSE_6 : { scsi_mode_sense6_resp_t mode_resp = { . data_len = 3 , . medium_type = 0 , . write_protected = false , . reserved = 0 , . block_descriptor_len = 0 } ; bool writable = true ; if ( tud_msc_is_writable_cb ) { writable = tud_msc_is_writable_cb ( p_cbw -> lun ) ; } mode_resp . write_protected = ! writable ; ret = sizeof ( mode_resp ) ; memcpy ( buffer , & mode_resp , ret ) ; } break ; case SCSI_CMD_REQUEST_SENSE : { scsi_sense_fixed_resp_t sense_rsp = { . response_code = 0x70 , . valid = 1 } ; sense_rsp . add_sense_len = sizeof ( scsi_sense_fixed_resp_t ) - 8 ; sense_rsp . sense_key = _mscd_itf . sense_key ; sense_rsp . add_sense_code = _mscd_itf . add_sense_code ; sense_rsp . add_sense_qualifier = _mscd_itf . add_sense_qualifier ; ret = sizeof ( sense_rsp ) ; memcpy ( buffer , & sense_rsp , ret ) ; tud_msc_set_sense ( p_cbw -> lun , 0 , 0 , 0 ) ; } break ; default : ret = -1 ; break ; } return ret ; }
return length of response (copied to buffer), -1 if it is not an built-in commands
return length of response ( copied to buffer ) - 1 if it is not an built - in commands
// TODO refractor later
 // formatted media
 // no block descriptor are included
 // Clear sense data after copy
