summaryrefslogtreecommitdiff
path: root/class
diff options
context:
space:
mode:
authorZhihong Chen <[email protected]>2024-02-06 11:25:39 +0800
committersakumisu <[email protected]>2024-02-06 18:31:47 +0800
commit920b02cb7c51fda01e334ccaabecc15c4e0d3480 (patch)
tree07784cc9ea1adfe6597ad0ac1d05520bf1fc3a3c /class
parent3f89d1b003083c458959dd52e1316b75a70f55fe (diff)
class: msc device: support multi lun
- support multi lun Signed-off-by: Zhihong Chen <[email protected]>
Diffstat (limited to 'class')
-rw-r--r--class/msc/usbd_msc.c93
-rw-r--r--class/msc/usbd_msc.h7
2 files changed, 57 insertions, 43 deletions
diff --git a/class/msc/usbd_msc.c b/class/msc/usbd_msc.c
index 45df1b3c..d6e22d79 100644
--- a/class/msc/usbd_msc.c
+++ b/class/msc/usbd_msc.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, sakumisu
+ * Copyright (c) 2024, zhihong chen
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -40,8 +41,8 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
uint8_t max_lun;
uint32_t start_sector;
uint32_t nsectors;
- uint16_t scsi_blk_size;
- uint32_t scsi_blk_nbr;
+ uint32_t scsi_blk_size[CONFIG_USBDEV_MSC_MAX_LUN];
+ uint32_t scsi_blk_nbr[CONFIG_USBDEV_MSC_MAX_LUN];
USB_MEM_ALIGNX uint8_t block_buffer[CONFIG_USBDEV_MSC_MAX_BUFSIZE];
@@ -52,6 +53,15 @@ USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
#endif
} g_usbd_msc;
+#ifdef CONFIG_USBDEV_MSC_THREAD
+static void usbdev_msc_thread(void *argument);
+#endif
+
+static void usdb_msc_set_max_lun(void)
+{
+ g_usbd_msc.max_lun = CONFIG_USBDEV_MSC_MAX_LUN - 1u;
+}
+
static void usbd_msc_reset(void)
{
g_usbd_msc.stage = MSC_READ_CBW;
@@ -448,15 +458,15 @@ static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
0x00,
0x00,
0x08, /* Capacity List Length */
- (uint8_t)((g_usbd_msc.scsi_blk_nbr >> 24) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_nbr >> 16) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_nbr >> 8) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_nbr >> 0) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] >> 24) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] >> 16) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] >> 8) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] >> 0) & 0xff),
0x02, /* Descriptor Code: Formatted Media */
0x00,
- (uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN] >> 8) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN] >> 0) & 0xff),
};
memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF);
@@ -472,15 +482,15 @@ static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
}
uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
- (uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 24) & 0xff),
- (uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 16) & 0xff),
- (uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 8) & 0xff),
- (uint8_t)(((g_usbd_msc.scsi_blk_nbr - 1) >> 0) & 0xff),
+ (uint8_t)(((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] - 1) >> 24) & 0xff),
+ (uint8_t)(((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] - 1) >> 16) & 0xff),
+ (uint8_t)(((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] - 1) >> 8) & 0xff),
+ (uint8_t)(((g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN] - 1) >> 0) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_size >> 24) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_size >> 16) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_size >> 8) & 0xff),
- (uint8_t)((g_usbd_msc.scsi_blk_size >> 0) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN] >> 24) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN] >> 16) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN] >> 8) & 0xff),
+ (uint8_t)((g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN] >> 0) & 0xff),
};
memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
@@ -501,13 +511,13 @@ static bool SCSI_read10(uint8_t **data, uint32_t *len)
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
- if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
+ if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN]) {
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
- if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
+ if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN])) {
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
return false;
}
@@ -533,13 +543,13 @@ static bool SCSI_read12(uint8_t **data, uint32_t *len)
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
- if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
+ if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN]) {
SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
- if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size)) {
+ if (g_usbd_msc.cbw.dDataLength != (g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN])) {
USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
return false;
}
@@ -566,8 +576,8 @@ static bool SCSI_write10(uint8_t **data, uint32_t *len)
g_usbd_msc.nsectors = GET_BE16(&g_usbd_msc.cbw.CB[7]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
- data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
- if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
+ data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN];
+ if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN]) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
@@ -595,8 +605,8 @@ static bool SCSI_write12(uint8_t **data, uint32_t *len)
g_usbd_msc.nsectors = GET_BE32(&g_usbd_msc.cbw.CB[6]); /* Number of Blocks to transfer */
USB_LOG_DBG("nsectors: 0x%02x\r\n", g_usbd_msc.nsectors);
- data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size;
- if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr) {
+ data_len = g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN];
+ if ((g_usbd_msc.start_sector + g_usbd_msc.nsectors) > g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN]) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
@@ -634,15 +644,15 @@ static bool SCSI_verify10(uint8_t **data, uint32_t *len)
lba = GET_BE32(&g_usbd_msc.cbw.CB[2]);
USB_LOG_DBG("lba: 0x%x\r\n", lba);
- g_usbd_msc.scsi_blk_addr = lba * g_usbd_msc.scsi_blk_size;
+ g_usbd_msc.scsi_blk_addr = lba * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN];
/* Number of Blocks to transfer */
blk_num = GET_BE16(&g_usbd_msc.cbw.CB[7]);
USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num);
- g_usbd_msc.scsi_blk_len = blk_num * g_usbd_msc.scsi_blk_size;
+ g_usbd_msc.scsi_blk_len = blk_num * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN];
- if ((lba + blk_num) > g_usbd_msc.scsi_blk_nbr) {
+ if ((lba + blk_num) > g_usbd_msc.scsi_blk_nbr[g_usbd_msc.cbw.bLUN]) {
USB_LOG_ERR("LBA out of range\r\n");
return false;
}
@@ -662,17 +672,17 @@ static bool SCSI_processRead(void)
USB_LOG_DBG("read lba:%d\r\n", g_usbd_msc.start_sector);
- transfer_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_MAX_BUFSIZE);
+ transfer_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN], CONFIG_USBDEV_MSC_MAX_BUFSIZE);
- if (usbd_msc_sector_read(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, transfer_len) != 0) {
+ if (usbd_msc_sector_read(g_usbd_msc.cbw.bLUN, g_usbd_msc.start_sector, g_usbd_msc.block_buffer, transfer_len) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
return false;
}
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, g_usbd_msc.block_buffer, transfer_len);
- g_usbd_msc.start_sector += (transfer_len / g_usbd_msc.scsi_blk_size);
- g_usbd_msc.nsectors -= (transfer_len / g_usbd_msc.scsi_blk_size);
+ g_usbd_msc.start_sector += (transfer_len / g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN]);
+ g_usbd_msc.nsectors -= (transfer_len / g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN]);
g_usbd_msc.csw.dDataResidue -= transfer_len;
if (g_usbd_msc.nsectors == 0) {
@@ -687,19 +697,19 @@ static bool SCSI_processWrite(uint32_t nbytes)
uint32_t data_len = 0;
USB_LOG_DBG("write lba:%d\r\n", g_usbd_msc.start_sector);
- if (usbd_msc_sector_write(g_usbd_msc.start_sector, g_usbd_msc.block_buffer, nbytes) != 0) {
+ if (usbd_msc_sector_write(g_usbd_msc.cbw.bLUN, g_usbd_msc.start_sector, g_usbd_msc.block_buffer, nbytes) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
return false;
}
- g_usbd_msc.start_sector += (nbytes / g_usbd_msc.scsi_blk_size);
- g_usbd_msc.nsectors -= (nbytes / g_usbd_msc.scsi_blk_size);
+ g_usbd_msc.start_sector += (nbytes / g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN]);
+ g_usbd_msc.nsectors -= (nbytes / g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN]);
g_usbd_msc.csw.dDataResidue -= nbytes;
if (g_usbd_msc.nsectors == 0) {
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
} else {
- data_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size, CONFIG_USBDEV_MSC_MAX_BUFSIZE);
+ data_len = MIN(g_usbd_msc.nsectors * g_usbd_msc.scsi_blk_size[g_usbd_msc.cbw.bLUN], CONFIG_USBDEV_MSC_MAX_BUFSIZE);
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, g_usbd_msc.block_buffer, data_len);
}
@@ -721,7 +731,7 @@ static bool SCSI_CBWDecode(uint32_t nbytes)
g_usbd_msc.csw.dTag = g_usbd_msc.cbw.dTag;
g_usbd_msc.csw.dDataResidue = g_usbd_msc.cbw.dDataLength;
- if ((g_usbd_msc.cbw.bLUN > 1) || (g_usbd_msc.cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc.cbw.bCBLength < 1) || (g_usbd_msc.cbw.bCBLength > 16)) {
+ if ((g_usbd_msc.cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc.cbw.bCBLength < 1) || (g_usbd_msc.cbw.bCBLength > 16)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
} else {
@@ -903,11 +913,14 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf, const uin
memset((uint8_t *)&g_usbd_msc, 0, sizeof(struct usbd_msc_priv));
- usbd_msc_get_cap(0, &g_usbd_msc.scsi_blk_nbr, &g_usbd_msc.scsi_blk_size);
+ usdb_msc_set_max_lun();
+ for (uint8_t i = 0u; i <= g_usbd_msc.max_lun; i++) {
+ usbd_msc_get_cap(i, &g_usbd_msc.scsi_blk_nbr[i], &g_usbd_msc.scsi_blk_size[i]);
- if (g_usbd_msc.scsi_blk_size > CONFIG_USBDEV_MSC_MAX_BUFSIZE) {
- USB_LOG_ERR("msc block buffer overflow\r\n");
- return NULL;
+ if (g_usbd_msc.scsi_blk_size[i] > CONFIG_USBDEV_MSC_MAX_BUFSIZE) {
+ USB_LOG_ERR("msc block buffer overflow\r\n");
+ return NULL;
+ }
}
return intf;
diff --git a/class/msc/usbd_msc.h b/class/msc/usbd_msc.h
index 022f046d..43fa8ba8 100644
--- a/class/msc/usbd_msc.h
+++ b/class/msc/usbd_msc.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, sakumisu
+ * Copyright (c) 2024, zhihong chen
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -17,9 +18,9 @@ struct usbd_interface *usbd_msc_init_intf(struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep);
-void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
-int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
-int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
+void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint32_t *block_size);
+int usbd_msc_sector_read(uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
+int usbd_msc_sector_write(uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length);
void usbd_msc_set_readonly(bool readonly);
bool usbd_msc_set_popup(void);