Skip to content

Commit e28b1dd

Browse files
committed
Device MSC: add START STOP (load/eject) request support
- Add mass-storage “removable media” support by tracking per-LUN prevent/allow medium removal and loaded/ejected status. - Introduce an optional per-LUN callback to handle SCSI START STOP UNIT (including load/eject and power-condition fields). - Extend storage constants (media types, sense keys/codes, power conditions, prevent flags) to support the new behavior and improve readability (explicit hex values). - Initialize new per-LUN state on activation (default: medium removal allowed, medium loaded) and wire the new callback through storage initialization. - Includes minor formatting/comment cleanups and version banner updates to 6.4.6. SCSI Block Commands – 4 (SBC-4)
1 parent 515c9a4 commit e28b1dd

13 files changed

+1145
-377
lines changed

common/usbx_device_classes/inc/ux_device_class_storage.h

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/***************************************************************************
2-
* Copyright (c) 2024 Microsoft Corporation
3-
*
2+
* Copyright (c) 2024 Microsoft Corporation
3+
*
44
* This program and the accompanying materials are made available under the
55
* terms of the MIT License which is available at
66
* https://opensource.org/licenses/MIT.
7-
*
7+
*
88
* SPDX-License-Identifier: MIT
99
**************************************************************************/
1010

@@ -67,15 +67,15 @@
6767
#ifndef UX_DEVICE_CLASS_STORAGE_H
6868
#define UX_DEVICE_CLASS_STORAGE_H
6969

70-
/* Determine if a C++ compiler is being used. If so, ensure that standard
71-
C is used to process the API information. */
70+
/* Determine if a C++ compiler is being used. If so, ensure that standard
71+
C is used to process the API information. */
7272

73-
#ifdef __cplusplus
73+
#ifdef __cplusplus
7474

75-
/* Yes, C++ compiler is present. Use standard C. */
76-
extern "C" {
75+
/* Yes, C++ compiler is present. Use standard C. */
76+
extern "C" {
7777

78-
#endif
78+
#endif
7979

8080

8181
/* Internal option: enable the basic USBX error checking. This define is typically used
@@ -112,7 +112,10 @@ extern "C" {
112112
#define UX_SLAVE_CLASS_STORAGE_MEDIA_OPTICAL_DISK 7
113113
#define UX_SLAVE_CLASS_STORAGE_MEDIA_IOMEGA_CLICK 0x55
114114

115+
/* Define Storage Class USB medium removable type. */
115116

117+
#define UX_SLAVE_CLASS_STORAGE_MEDIA_IS_NOT_REMOVABLE 0x00
118+
#define UX_SLAVE_CLASS_STORAGE_MEDIA_IS_REMOVABLE (1u<<8)
116119

117120
/* Define Storage Class SCSI command constants. */
118121

@@ -321,6 +324,10 @@ extern "C" {
321324
#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_VOLUME_OVERFLOW 0x0d
322325
#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_MISCOMPARE 0x0e
323326

327+
#define UX_SLAVE_CLASS_STORAGE_SENSE_CODE_NOT_READY 0x04
328+
#define UX_SLAVE_CLASS_STORAGE_SENSE_CODE_WRITE_PROTECTED 0x27
329+
#define UX_SLAVE_CLASS_STORAGE_SENSE_CODE_NOT_READY_TO_READY 0x28
330+
#define UX_SLAVE_CLASS_STORAGE_SENSE_CODE_NOT_PRESENT 0x3A
324331

325332
/* Define Storage Class SCSI sense key definition constants. */
326333

@@ -361,6 +368,23 @@ extern "C" {
361368
#define UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_ALLOCATION_LENGTH 7
362369
#define UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_LENGTH 10
363370

371+
/* Define Storage Class (SBC-4) POWER CONDITION constants. */
372+
373+
#define UX_SLAVE_CLASS_STORAGE_POWER_CONDITION_START_VALID 0x00
374+
#define UX_SLAVE_CLASS_STORAGE_POWER_CONDITION_ACTIVE 0x01
375+
#define UX_SLAVE_CLASS_STORAGE_POWER_CONDITION_IDLE 0x02
376+
#define UX_SLAVE_CLASS_STORAGE_POWER_CONDITION_STANDBY 0x03
377+
#define UX_SLAVE_CLASS_STORAGE_POWER_CONDITION_LU_CONTROL 0x07
378+
#define UX_SLAVE_CLASS_STORAGE_POWER_CONDITION_FORCE_IDLE_0 0x0A
379+
#define UX_SLAVE_CLASS_STORAGE_POWER_CONDITION_FORCE_STANDBY_0 0x0B
380+
381+
/* Define Storage Class (SBC-4) PREVENT constants. */
382+
383+
#define UX_SLAVE_CLASS_STORAGE_MEDIUM_REMOVAL_IS_ALLOWED 0x00
384+
#define UX_SLAVE_CLASS_STORAGE_MEDIUM_REMOVAL_SHALL_BE_PREVENTED 0x01
385+
#define UX_SLAVE_CLASS_STORAGE_MEDIUM_PREVENT_OBSOLETE_2 0x02
386+
#define UX_SLAVE_CLASS_STORAGE_MEDIUM_PREVENT_OBSOLETE_3 0x03
387+
364388
/* Define Storage Class Feature Descriptor generic format. */
365389

366390
#define USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_CODE 0
@@ -504,12 +528,17 @@ typedef struct UX_SLAVE_CLASS_STORAGE_LUN_STRUCT
504528
ULONG ux_slave_class_storage_request_sense_status;
505529
ULONG ux_slave_class_storage_disk_status;
506530
ULONG ux_slave_class_storage_last_session_state;
531+
ULONG ux_slave_class_storage_prevent_medium_removal;
532+
ULONG ux_slave_class_storage_medium_loaded_status;
507533

508534
UINT (*ux_slave_class_storage_media_read)(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status);
509535
UINT (*ux_slave_class_storage_media_write)(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status);
510536
UINT (*ux_slave_class_storage_media_flush)(VOID *storage, ULONG lun, ULONG number_blocks, ULONG lba, ULONG *media_status);
511537
UINT (*ux_slave_class_storage_media_status)(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status);
512538
UINT (*ux_slave_class_storage_media_notification)(VOID *storage, ULONG lun, ULONG media_id, ULONG notification_class, UCHAR **media_notification, ULONG *media_notification_length);
539+
540+
/* Optional callback invoked when load/eject media is requested. */
541+
UINT (*ux_slave_class_storage_media_start_stop)(VOID *storage, ULONG lun, ULONG power_condition, ULONG start, ULONG load_eject);
513542
} UX_SLAVE_CLASS_STORAGE_LUN;
514543

515544
/* Sense status value (key at bit0-7, code at bit8-15 and qualifier at bit16-23). */
@@ -674,10 +703,10 @@ UINT _uxe_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND *command);
674703

675704
#define ux_device_class_storage_entry _ux_device_class_storage_entry
676705

677-
/* Determine if a C++ compiler is being used. If so, complete the standard
678-
C conditional started above. */
706+
/* Determine if a C++ compiler is being used. If so, complete the standard
707+
C conditional started above. */
679708
#ifdef __cplusplus
680-
}
681-
#endif
709+
}
710+
#endif
682711

683712
#endif

common/usbx_device_classes/src/ux_device_class_storage_activate.c

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
/***************************************************************************
2-
* Copyright (c) 2024 Microsoft Corporation
3-
*
2+
* Copyright (c) 2024 Microsoft Corporation
3+
*
44
* This program and the accompanying materials are made available under the
55
* terms of the MIT License which is available at
66
* https://opensource.org/licenses/MIT.
7-
*
7+
*
88
* SPDX-License-Identifier: MIT
99
**************************************************************************/
1010

1111

1212
/**************************************************************************/
1313
/**************************************************************************/
14-
/** */
15-
/** USBX Component */
14+
/** */
15+
/** USBX Component */
1616
/** */
1717
/** Device Storage Class */
1818
/** */
@@ -29,40 +29,40 @@
2929
#include "ux_device_stack.h"
3030

3131

32-
/**************************************************************************/
33-
/* */
34-
/* FUNCTION RELEASE */
35-
/* */
36-
/* _ux_device_class_storage_activate PORTABLE C */
32+
/**************************************************************************/
33+
/* */
34+
/* FUNCTION RELEASE */
35+
/* */
36+
/* _ux_device_class_storage_activate PORTABLE C */
3737
/* 6.3.0 */
3838
/* AUTHOR */
3939
/* */
4040
/* Chaoqiong Xiao, Microsoft Corporation */
4141
/* */
4242
/* DESCRIPTION */
43-
/* */
44-
/* This function activates the USB storage device. */
45-
/* */
46-
/* INPUT */
47-
/* */
48-
/* command Pointer to storage command */
49-
/* */
50-
/* OUTPUT */
51-
/* */
52-
/* Completion Status */
53-
/* */
54-
/* CALLS */
55-
/* */
56-
/* _ux_device_thread_resume Resume thread */
57-
/* */
58-
/* CALLED BY */
59-
/* */
60-
/* Device Storage Class */
61-
/* */
62-
/* RELEASE HISTORY */
63-
/* */
64-
/* DATE NAME DESCRIPTION */
65-
/* */
43+
/* */
44+
/* This function activates the USB storage device. */
45+
/* */
46+
/* INPUT */
47+
/* */
48+
/* command Pointer to storage command */
49+
/* */
50+
/* OUTPUT */
51+
/* */
52+
/* Completion Status */
53+
/* */
54+
/* CALLS */
55+
/* */
56+
/* _ux_device_thread_resume Resume thread */
57+
/* */
58+
/* CALLED BY */
59+
/* */
60+
/* Device Storage Class */
61+
/* */
62+
/* RELEASE HISTORY */
63+
/* */
64+
/* DATE NAME DESCRIPTION */
65+
/* */
6666
/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
6767
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
6868
/* resulting in version 6.1 */
@@ -81,11 +81,12 @@
8181
/**************************************************************************/
8282
UINT _ux_device_class_storage_activate(UX_SLAVE_CLASS_COMMAND *command)
8383
{
84-
84+
8585
UINT status = UX_SUCCESS;
8686
UX_SLAVE_INTERFACE *interface_ptr;
8787
UX_SLAVE_CLASS *class_ptr;
8888
UX_SLAVE_CLASS_STORAGE *storage;
89+
ULONG lun_index;
8990
#if defined(UX_DEVICE_STANDALONE)
9091
UX_SLAVE_ENDPOINT *endpoint;
9192
#endif
@@ -99,17 +100,17 @@ UX_SLAVE_ENDPOINT *endpoint;
99100

100101
/* Get the interface that owns this instance. */
101102
interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
102-
103+
103104
/* Store the class instance into the interface. */
104105
interface_ptr -> ux_slave_interface_class_instance = (VOID *)storage;
105-
106+
106107
/* Now the opposite, store the interface in the class instance. */
107108
storage -> ux_slave_class_storage_interface = interface_ptr;
108109

109110
#if !defined(UX_DEVICE_STANDALONE)
110111

111112
/* Resume thread. */
112-
_ux_device_thread_resume(&class_ptr -> ux_slave_class_thread);
113+
_ux_device_thread_resume(&class_ptr -> ux_slave_class_thread);
113114

114115
#else
115116

@@ -130,7 +131,7 @@ UX_SLAVE_ENDPOINT *endpoint;
130131

131132
/* We found the IN endpoint first. */
132133
storage -> ux_device_class_storage_ep_in = endpoint;
133-
134+
134135
/* So the next endpoint has to be the OUT endpoint. */
135136
storage -> ux_device_class_storage_ep_out = endpoint -> ux_slave_endpoint_next_endpoint;
136137
}
@@ -162,13 +163,20 @@ UX_SLAVE_ENDPOINT *endpoint;
162163
status = UX_SUCCESS;
163164
#endif
164165

166+
/* Default when activating storage device: media removal is allowed (not prevented) and loaded. */
167+
for (lun_index = 0; lun_index < storage -> ux_slave_class_storage_number_lun; lun_index++)
168+
{
169+
storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_prevent_medium_removal = 0;
170+
storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_medium_loaded_status = 1;
171+
}
172+
165173
/* If there is a activate function call it. */
166174
if (storage -> ux_slave_class_storage_instance_activate != UX_NULL)
167-
{
175+
{
168176
/* Invoke the application. */
169177
storage -> ux_slave_class_storage_instance_activate(storage);
170178
}
171-
179+
172180
/* If trace is enabled, insert this event into the trace buffer. */
173181
UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_ACTIVATE, storage, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
174182

common/usbx_device_classes/src/ux_device_class_storage_initialize.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ ULONG lun_index;
184184
storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_write = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_write;
185185
storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_status = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_status;
186186
storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_notification = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_notification;
187+
storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_start_stop = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_start_stop;
187188
}
188189

189190
/* If it's OK, complete it. */

0 commit comments

Comments
 (0)