Skip to content

Commit b9e6659

Browse files
mattiam-delvgololobov
authored andcommitted
tests: usbh: msc: Extended msc test suite with error paths
Signed-off-by: Mattia Maldini <mattia.m@embedd.it>
1 parent af1c81f commit b9e6659

8 files changed

Lines changed: 368 additions & 9 deletions

File tree

subsys/usb/host/class/usbh_msc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,9 +617,9 @@ static int check_sense(struct driver_data *driver_data, uint8_t lun_index)
617617
sense_data.additional_sense_code == SCSI_SENSE_DATA_ASC_NOT_READY_TO_READY) {
618618
result = -EAGAIN;
619619
}
620-
/* Somehow medium was removed */
620+
/* Medium error, may disappear on retry */
621621
else if (sense_data.sense_key == SCSI_SENSE_DATA_KEY_MEDIUM_ERROR) {
622-
result = -ENOMEDIUM;
622+
result = -EIO;
623623
} else if (sense_data.additional_sense_code ==
624624
SCSI_SENSE_DATA_ASC_MEDIUM_NOT_PRESENT) {
625625
result = -ENOMEDIUM;

tests/subsys/usb/msc/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/usb/host)
1616
target_sources(app PRIVATE src/msc.c)
1717

1818
if(${BOARD} STREQUAL "native_sim")
19-
target_sources(app PRIVATE src/ram_disk.c)
19+
target_sources(app PRIVATE src/ram_disk.c src/fault_disk.c)
2020
endif()

tests/subsys/usb/msc/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ config SYS_CLOCK_TICKS_PER_SEC
66

77
config TEST_NUM_LUN
88
int
9-
default 2 if BOARD_NATIVE_SIM
9+
default 3 if BOARD_NATIVE_SIM
1010
default 1
1111

1212
# Source common USB sample options used to initialize new experimental USB

tests/subsys/usb/msc/prj.conf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ CONFIG_USBH_MSC_CLASS=y
1616
CONFIG_UART_LINE_CTRL=y
1717

1818
CONFIG_USBD_MSC_CLASS=y
19-
CONFIG_USBH_MSC_MAX_SUPPORTED_LUN=2
20-
CONFIG_USBD_MSC_LUNS_PER_INSTANCE=2
19+
CONFIG_USBH_MSC_MAX_SUPPORTED_LUN=3
20+
CONFIG_USBD_MSC_LUNS_PER_INSTANCE=3
2121
CONFIG_USBD_MSC_SCSI_BUFFER_SIZE=1024
2222
CONFIG_FS_FATFS_MAX_SS=1024
2323
CONFIG_FILE_SYSTEM=y
@@ -35,7 +35,7 @@ CONFIG_ZTEST_STACK_SIZE=2048
3535
CONFIG_FS_FATFS_CUSTOM_MOUNT_POINT_COUNT=4
3636
CONFIG_FS_FATFS_CUSTOM_MOUNT_POINTS="RAM0,RAM1,USB0_0,USB0_1"
3737

38-
CONFIG_USBH_MSC_LOG_LEVEL_DBG=y
38+
CONFIG_USBH_MSC_LOG_LEVEL_INF=y
3939
CONFIG_USBH_LOG_LEVEL_INF=y
4040
CONFIG_UHC_DRIVER_LOG_LEVEL_INF=y
4141

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright 2026 Renesas, Embedd
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include <string.h>
7+
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/usb/class/usbd_msc.h>
10+
#include <zephyr/drivers/disk.h>
11+
#include <zephyr/storage/disk_access.h>
12+
13+
#include "fault_disk.h"
14+
15+
#define FAULT_DISK_SECTOR_SIZE 512u
16+
#define FAULT_DISK_SECTOR_COUNT 64u
17+
18+
/*
19+
* `USBD_DEFINE_MSC_LUN(id, ...)` places its LUN in the `usbd_msc_lun` iterable section, which
20+
* the linker sorts alphabetically by the resulting `usbd_msc_lun_##id` symbol name (SORT_BY_NAME,
21+
* see include/zephyr/linker/iterable_sections.h) -- NOT by declaration/link order. This id is
22+
* chosen to sort after ram_disk.c's "ram0"/"ram1" so this LUN lands last (index CONFIG_TEST_NUM_LUN
23+
* - 1, i.e. "USB0_2"), matching DISK_DRIVE_NAME_FAULT in msc.c.
24+
*/
25+
USBD_DEFINE_MSC_LUN(zzz_fault, FAULT_DISK_NAME, "Zephyr", "FaultDisk", "0.00");
26+
27+
static uint8_t backing[FAULT_DISK_SECTOR_COUNT][FAULT_DISK_SECTOR_SIZE];
28+
29+
/* -1: report the real status; otherwise the DISK_STATUS_* value to report instead */
30+
static int status_override = -1;
31+
static bool read_should_fail;
32+
static bool write_should_fail;
33+
34+
static int fault_disk_init(struct disk_info *disk)
35+
{
36+
ARG_UNUSED(disk);
37+
38+
return 0;
39+
}
40+
41+
static int fault_disk_status(struct disk_info *disk)
42+
{
43+
ARG_UNUSED(disk);
44+
45+
return status_override >= 0 ? status_override : DISK_STATUS_OK;
46+
}
47+
48+
static int fault_disk_read(struct disk_info *disk, uint8_t *data_buf, uint32_t start_sector,
49+
uint32_t num_sector)
50+
{
51+
ARG_UNUSED(disk);
52+
53+
if (read_should_fail) {
54+
return -EIO;
55+
}
56+
57+
if (start_sector + num_sector > FAULT_DISK_SECTOR_COUNT) {
58+
return -EINVAL;
59+
}
60+
61+
memcpy(data_buf, backing[start_sector], (size_t)num_sector * FAULT_DISK_SECTOR_SIZE);
62+
63+
return 0;
64+
}
65+
66+
static int fault_disk_write(struct disk_info *disk, const uint8_t *data_buf, uint32_t start_sector,
67+
uint32_t num_sector)
68+
{
69+
ARG_UNUSED(disk);
70+
71+
if (write_should_fail) {
72+
return -EIO;
73+
}
74+
75+
if (start_sector + num_sector > FAULT_DISK_SECTOR_COUNT) {
76+
return -EINVAL;
77+
}
78+
79+
memcpy(backing[start_sector], data_buf, (size_t)num_sector * FAULT_DISK_SECTOR_SIZE);
80+
81+
return 0;
82+
}
83+
84+
static int fault_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff)
85+
{
86+
ARG_UNUSED(disk);
87+
88+
switch (cmd) {
89+
case DISK_IOCTL_GET_SECTOR_COUNT:
90+
*(uint32_t *)buff = FAULT_DISK_SECTOR_COUNT;
91+
return 0;
92+
case DISK_IOCTL_GET_SECTOR_SIZE:
93+
*(uint32_t *)buff = FAULT_DISK_SECTOR_SIZE;
94+
return 0;
95+
case DISK_IOCTL_CTRL_SYNC:
96+
case DISK_IOCTL_CTRL_INIT:
97+
case DISK_IOCTL_CTRL_DEINIT:
98+
return 0;
99+
default:
100+
return -ENOTSUP;
101+
}
102+
}
103+
104+
static const struct disk_operations fault_disk_ops = {
105+
.init = fault_disk_init,
106+
.status = fault_disk_status,
107+
.read = fault_disk_read,
108+
.write = fault_disk_write,
109+
.ioctl = fault_disk_ioctl,
110+
};
111+
112+
static struct disk_info fault_disk_info = {
113+
.name = FAULT_DISK_NAME,
114+
.ops = &fault_disk_ops,
115+
};
116+
117+
void fault_disk_setup(void)
118+
{
119+
disk_access_register(&fault_disk_info);
120+
}
121+
122+
void fault_disk_reset(void)
123+
{
124+
status_override = -1;
125+
read_should_fail = false;
126+
write_should_fail = false;
127+
}
128+
129+
void fault_disk_set_status_override(int status)
130+
{
131+
status_override = status;
132+
}
133+
134+
void fault_disk_set_read_error(bool fail)
135+
{
136+
read_should_fail = fail;
137+
}
138+
139+
void fault_disk_set_write_error(bool fail)
140+
{
141+
write_should_fail = fail;
142+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright 2026 Renesas, Embedd
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef FAULT_DISK_H_INCLUDED
7+
#define FAULT_DISK_H_INCLUDED
8+
9+
#include <stdbool.h>
10+
11+
/* Disk name as registered with the Disk Access API and exposed as a third MSC LUN */
12+
#define FAULT_DISK_NAME "FAULT0"
13+
14+
/**
15+
* @brief Register the simulated fault-injectable disk
16+
*/
17+
void fault_disk_setup(void);
18+
19+
/**
20+
* @brief Clear all fault injection, restoring normal disk behavior
21+
*/
22+
void fault_disk_reset(void);
23+
24+
/**
25+
* @brief Override the value reported by the disk's status callback
26+
*
27+
* @param status A DISK_STATUS_* value to report, or -1 to report the real (normal) status
28+
*/
29+
void fault_disk_set_status_override(int status);
30+
31+
/**
32+
* @brief Force (or stop forcing) the next reads to fail
33+
*
34+
* @param fail true to make reads fail, false to let them succeed normally
35+
*/
36+
void fault_disk_set_read_error(bool fail);
37+
38+
/**
39+
* @brief Force (or stop forcing) the next writes to fail
40+
*
41+
* @param fail true to make writes fail, false to let them succeed normally
42+
*/
43+
void fault_disk_set_write_error(bool fail);
44+
45+
#endif /* FAULT_DISK_H_INCLUDED */

0 commit comments

Comments
 (0)