Add SAMD21 and SAMD51 support for CircuitPython.
The ProtoThreads style subtasks were removed because it led to extremely unclear control flow. RTOSes can be used if threading is needed. Also added some additional functionality to MSC to support dynamic LUNs and read-only LUNs.
This commit is contained in:
@@ -279,11 +279,13 @@ typedef struct ATTR_PACKED
|
||||
|
||||
TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct");
|
||||
|
||||
// This is only a Mode parameter header(6).
|
||||
typedef struct ATTR_PACKED
|
||||
{
|
||||
uint8_t data_len;
|
||||
uint8_t medium_type;
|
||||
uint8_t device_specific_para;
|
||||
bool write_protected : 1;
|
||||
uint8_t reserved : 7;
|
||||
uint8_t block_descriptor_len;
|
||||
} scsi_mode_sense6_resp_t;
|
||||
|
||||
|
||||
@@ -59,31 +59,7 @@ enum
|
||||
MSC_STAGE_STATUS
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
CFG_TUSB_MEM_ALIGN msc_cbw_t cbw;
|
||||
|
||||
//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
|
||||
// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member
|
||||
//#endif
|
||||
|
||||
CFG_TUSB_MEM_ALIGN msc_csw_t csw;
|
||||
|
||||
uint8_t itf_num;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
// Bulk Only Transfer (BOT) Protocol
|
||||
uint8_t stage;
|
||||
uint32_t total_len;
|
||||
uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage
|
||||
|
||||
// Sense Response Data
|
||||
uint8_t sense_key;
|
||||
uint8_t add_sense_code;
|
||||
uint8_t add_sense_qualifier;
|
||||
}mscd_interface_t;
|
||||
|
||||
CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf;
|
||||
CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN mscd_interface_t _mscd_itf;
|
||||
CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_BUFSIZE];
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -172,8 +148,6 @@ tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf,
|
||||
|
||||
tusb_error_t mscd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
OSAL_SUBTASK_BEGIN
|
||||
|
||||
TU_ASSERT(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT);
|
||||
|
||||
if(MSC_REQ_RESET == p_request->bRequest)
|
||||
@@ -189,10 +163,19 @@ tusb_error_t mscd_control_request_st(uint8_t rhport, tusb_control_request_t cons
|
||||
{
|
||||
dcd_control_stall(rhport); // stall unsupported request
|
||||
}
|
||||
|
||||
OSAL_SUBTASK_END
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
||||
// For backwards compatibility we support static block counts.
|
||||
#if defined(CFG_TUD_MSC_BLOCK_NUM) && defined(CFG_TUD_MSC_BLOCK_SZ)
|
||||
ATTR_WEAK bool tud_lun_capacity_cb(uint8_t lun, uint32_t* last_valid_sector, uint16_t* block_size) {
|
||||
(void) lun;
|
||||
*last_valid_sector = CFG_TUD_MSC_BLOCK_NUM-1;
|
||||
*block_size = CFG_TUD_MSC_BLOCK_SZ;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -202,11 +185,13 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
|
||||
{
|
||||
case SCSI_CMD_READ_CAPACITY_10:
|
||||
{
|
||||
scsi_read_capacity10_resp_t read_capa10 =
|
||||
{
|
||||
.last_lba = ENDIAN_BE(CFG_TUD_MSC_BLOCK_NUM-1), // read capacity
|
||||
.block_size = ENDIAN_BE(CFG_TUD_MSC_BLOCK_SZ)
|
||||
};
|
||||
scsi_read_capacity10_resp_t read_capa10;
|
||||
|
||||
uint32_t last_valid_sector;
|
||||
uint16_t block_size;
|
||||
tud_lun_capacity_cb(p_cbw->lun, &last_valid_sector, &block_size);
|
||||
read_capa10.last_lba = ENDIAN_BE(last_valid_sector); // read capacity
|
||||
read_capa10.block_size = ENDIAN_BE(block_size);
|
||||
|
||||
ret = sizeof(read_capa10);
|
||||
memcpy(buffer, &read_capa10, ret);
|
||||
@@ -218,11 +203,17 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
|
||||
scsi_read_format_capacity_data_t read_fmt_capa =
|
||||
{
|
||||
.list_length = 8,
|
||||
.block_num = ENDIAN_BE(CFG_TUD_MSC_BLOCK_NUM), // write capacity
|
||||
.block_num = 0,
|
||||
.descriptor_type = 2, // formatted media
|
||||
.block_size_u16 = ENDIAN_BE16(CFG_TUD_MSC_BLOCK_SZ)
|
||||
.block_size_u16 = 0
|
||||
};
|
||||
|
||||
uint32_t last_valid_sector;
|
||||
uint16_t block_size;
|
||||
tud_lun_capacity_cb(p_cbw->lun, &last_valid_sector, &block_size);
|
||||
read_fmt_capa.block_num = ENDIAN_BE(last_valid_sector+1);
|
||||
read_fmt_capa.block_size_u16 = ENDIAN_BE16(block_size);
|
||||
|
||||
ret = sizeof(read_fmt_capa);
|
||||
memcpy(buffer, &read_fmt_capa, ret);
|
||||
}
|
||||
@@ -251,13 +242,21 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
|
||||
|
||||
case SCSI_CMD_MODE_SENSE_6:
|
||||
{
|
||||
scsi_mode_sense6_resp_t const mode_resp = {
|
||||
.data_len = 3,
|
||||
.medium_type = 0,
|
||||
.device_specific_para = 0,
|
||||
.block_descriptor_len = 0 // no block descriptor are included
|
||||
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);
|
||||
}
|
||||
@@ -291,7 +290,7 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
|
||||
return ret;
|
||||
}
|
||||
|
||||
tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes)
|
||||
tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, uint8_t event, uint32_t xferred_bytes)
|
||||
{
|
||||
mscd_interface_t* p_msc = &_mscd_itf;
|
||||
msc_cbw_t const * p_cbw = &p_msc->cbw;
|
||||
@@ -425,7 +424,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u
|
||||
}else
|
||||
{
|
||||
// Application consume less than what we got (including zero)
|
||||
if ( nbytes < xferred_bytes )
|
||||
if ( nbytes < (int32_t) xferred_bytes )
|
||||
{
|
||||
if ( nbytes > 0 )
|
||||
{
|
||||
|
||||
@@ -55,14 +55,6 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct");
|
||||
#error MSC Device: Incorrect setting of MAX LUN
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_MSC_BLOCK_NUM
|
||||
#error CFG_TUD_MSC_BLOCK_NUM must be defined
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_MSC_BLOCK_SZ
|
||||
#error CFG_TUD_MSC_BLOCK_SZ must be defined
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_MSC_BUFSIZE
|
||||
#error CFG_TUD_MSC_BUFSIZE must be defined, value of CFG_TUD_MSC_BLOCK_SZ should work well, the more the better
|
||||
#endif
|
||||
@@ -89,6 +81,32 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct");
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
CFG_TUSB_MEM_ALIGN msc_cbw_t cbw;
|
||||
|
||||
//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
|
||||
// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member
|
||||
//#endif
|
||||
|
||||
CFG_TUSB_MEM_ALIGN msc_csw_t csw;
|
||||
|
||||
uint8_t itf_num;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
// Bulk Only Transfer (BOT) Protocol
|
||||
uint8_t stage;
|
||||
uint32_t total_len;
|
||||
uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage
|
||||
|
||||
// Sense Response Data
|
||||
uint8_t sense_key;
|
||||
uint8_t add_sense_code;
|
||||
uint8_t add_sense_qualifier;
|
||||
}mscd_interface_t;
|
||||
|
||||
extern mscd_interface_t _mscd_itf;
|
||||
|
||||
/** \addtogroup ClassDriver_MSC
|
||||
* @{
|
||||
* \defgroup MSC_Device Device
|
||||
@@ -138,7 +156,7 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf
|
||||
* \retval negative Indicate error writing disk I/O. Tinyusb will \b STALL the corresponding
|
||||
* endpoint and return failed status in command status wrapper phase.
|
||||
*/
|
||||
int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
|
||||
int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
|
||||
|
||||
/**
|
||||
* Callback invoked when received an SCSI command not in built-in list below.
|
||||
@@ -164,6 +182,12 @@ ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun);
|
||||
ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun);
|
||||
ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]);
|
||||
|
||||
// Hook to make a mass storage device read-only.
|
||||
ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun);
|
||||
|
||||
// Override for dynamic LUN sizes.
|
||||
ATTR_WEAK bool tud_lun_capacity_cb(uint8_t lun, uint32_t* last_valid_sector, uint16_t* block_size);
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
@@ -185,4 +209,3 @@ void mscd_reset(uint8_t rhport);
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_MSC_DEVICE_H_ */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user