blob: 84b6e4d799e9081b81004e35912e0a7f4489dfc6 [file] [log] [blame]
Austin Schuh41baf202022-01-01 14:33:40 -08001/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2019 Ha Thach (tinyusb.org)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#ifndef _TUSB_MSC_H_
28#define _TUSB_MSC_H_
29
30#include "common/tusb_common.h"
31
32#ifdef __cplusplus
33 extern "C" {
34#endif
35
36//--------------------------------------------------------------------+
37// Mass Storage Class Constant
38//--------------------------------------------------------------------+
39/// MassStorage Subclass
40typedef enum
41{
42 MSC_SUBCLASS_RBC = 1 , ///< Reduced Block Commands (RBC) T10 Project 1240-D
43 MSC_SUBCLASS_SFF_MMC , ///< SFF-8020i, MMC-2 (ATAPI). Typically used by a CD/DVD device
44 MSC_SUBCLASS_QIC , ///< QIC-157. Typically used by a tape device
45 MSC_SUBCLASS_UFI , ///< UFI. Typically used by Floppy Disk Drive (FDD) device
46 MSC_SUBCLASS_SFF , ///< SFF-8070i. Can be used by Floppy Disk Drive (FDD) device
47 MSC_SUBCLASS_SCSI ///< SCSI transparent command set
48}msc_subclass_type_t;
49
50enum {
51 MSC_CBW_SIGNATURE = 0x43425355, ///< Constant value of 43425355h (little endian)
52 MSC_CSW_SIGNATURE = 0x53425355 ///< Constant value of 53425355h (little endian)
53};
54
55/// \brief MassStorage Protocol.
56/// \details CBI only approved to use with full-speed floopy disk & should not used with highspeed or device other than floopy
57typedef enum
58{
59 MSC_PROTOCOL_CBI = 0 , ///< Control/Bulk/Interrupt protocol (with command completion interrupt)
60 MSC_PROTOCOL_CBI_NO_INTERRUPT = 1 , ///< Control/Bulk/Interrupt protocol (without command completion interrupt)
61 MSC_PROTOCOL_BOT = 0x50 ///< Bulk-Only Transport
62}msc_protocol_type_t;
63
64/// MassStorage Class-Specific Control Request
65typedef enum
66{
67 MSC_REQ_GET_MAX_LUN = 254, ///< The Get Max LUN device request is used to determine the number of logical units supported by the device. Logical Unit Numbers on the device shall be numbered contiguously starting from LUN 0 to a maximum LUN of 15
68 MSC_REQ_RESET = 255 ///< This request is used to reset the mass storage device and its associated interface. This class-specific request shall ready the device for the next CBW from the host.
69}msc_request_type_t;
70
71/// \brief Command Block Status Values
72/// \details Indicates the success or failure of the command. The device shall set this byte to zero if the command completed
73/// successfully. A non-zero value shall indicate a failure during command execution according to the following
74typedef enum
75{
76 MSC_CSW_STATUS_PASSED = 0 , ///< MSC_CSW_STATUS_PASSED
77 MSC_CSW_STATUS_FAILED , ///< MSC_CSW_STATUS_FAILED
78 MSC_CSW_STATUS_PHASE_ERROR ///< MSC_CSW_STATUS_PHASE_ERROR
79}msc_csw_status_t;
80
81/// Command Block Wrapper
82typedef struct TU_ATTR_PACKED
83{
84 uint32_t signature; ///< Signature that helps identify this data packet as a CBW. The signature field shall contain the value 43425355h (little endian), indicating a CBW.
85 uint32_t tag; ///< Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTagfield of the associated CSW. The dCSWTagpositively associates a CSW with the corresponding CBW.
86 uint32_t total_bytes; ///< The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during the execution of this command. If this field is zero, the device and the host shall transfer no data between the CBW and the associated CSW, and the device shall ignore the value of the Direction bit in bmCBWFlags.
87 uint8_t dir; ///< Bit 7 of this field define transfer direction \n - 0 : Data-Out from host to the device. \n - 1 : Data-In from the device to the host.
88 uint8_t lun; ///< The device Logical Unit Number (LUN) to which the command block is being sent. For devices that support multiple LUNs, the host shall place into this field the LUN to which this command block is addressed. Otherwise, the host shall set this field to zero.
89 uint8_t cmd_len; ///< The valid length of the CBWCBin bytes. This defines the valid length of the command block. The only legal values are 1 through 16
90 uint8_t command[16]; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block
91}msc_cbw_t;
92
93TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct");
94
95/// Command Status Wrapper
96typedef struct TU_ATTR_PACKED
97{
98 uint32_t signature ; ///< Signature that helps identify this data packet as a CSW. The signature field shall contain the value 53425355h (little endian), indicating CSW.
99 uint32_t tag ; ///< The device shall set this field to the value received in the dCBWTag of the associated CBW.
100 uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device
101 uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t
102}msc_csw_t;
103
104TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct");
105
106//--------------------------------------------------------------------+
107// SCSI Constant
108//--------------------------------------------------------------------+
109
110/// SCSI Command Operation Code
111typedef enum
112{
113 SCSI_CMD_TEST_UNIT_READY = 0x00, ///< The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/write), i.e. if a disk has spun up, if a tape is loaded and ready etc. The device does not perform a self-test operation.
114 SCSI_CMD_INQUIRY = 0x12, ///< The SCSI Inquiry command is used to obtain basic information from a target device.
115 SCSI_CMD_MODE_SELECT_6 = 0x15, ///< provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server. Device servers that implement the MODE SELECT(6) command shall also implement the MODE SENSE(6) command. Application clients should issue MODE SENSE(6) prior to each MODE SELECT(6) to determine supported mode pages, page lengths, and other parameters.
116 SCSI_CMD_MODE_SENSE_6 = 0x1A, ///< provides a means for a device server to report parameters to an application client. It is a complementary command to the MODE SELECT(6) command. Device servers that implement the MODE SENSE(6) command shall also implement the MODE SELECT(6) command.
117 SCSI_CMD_START_STOP_UNIT = 0x1B,
118 SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E,
119 SCSI_CMD_READ_CAPACITY_10 = 0x25, ///< The SCSI Read Capacity command is used to obtain data capacity information from a target device.
120 SCSI_CMD_REQUEST_SENSE = 0x03, ///< The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used to obtain sense data -- status/error information -- from a target device.
121 SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, ///< The command allows the Host to request a list of the possible format capacities for an installed writable media. This command also has the capability to report the writable capacity for a media when it is installed
122 SCSI_CMD_READ_10 = 0x28, ///< The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer.
123 SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from the data-out buffer and write them.
124}scsi_cmd_type_t;
125
126/// SCSI Sense Key
127typedef enum
128{
129 SCSI_SENSE_NONE = 0x00, ///< no specific Sense Key. This would be the case for a successful command
130 SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< ndicates the last command completed successfully with some recovery action performed by the disc drive.
131 SCSI_SENSE_NOT_READY = 0x02, ///< Indicates the logical unit addressed cannot be accessed.
132 SCSI_SENSE_MEDIUM_ERROR = 0x03, ///< Indicates the command terminated with a non-recovered error condition.
133 SCSI_SENSE_HARDWARE_ERROR = 0x04, ///< Indicates the disc drive detected a nonrecoverable hardware failure while performing the command or during a self test.
134 SCSI_SENSE_ILLEGAL_REQUEST = 0x05, ///< Indicates an illegal parameter in the command descriptor block or in the additional parameters
135 SCSI_SENSE_UNIT_ATTENTION = 0x06, ///< Indicates the disc drive may have been reset.
136 SCSI_SENSE_DATA_PROTECT = 0x07, ///< Indicates that a command that reads or writes the medium was attempted on a block that is protected from this operation. The read or write operation is not performed.
137 SCSI_SENSE_FIRMWARE_ERROR = 0x08, ///< Vendor specific sense key.
138 SCSI_SENSE_ABORTED_COMMAND = 0x0b, ///< Indicates the disc drive aborted the command.
139 SCSI_SENSE_EQUAL = 0x0c, ///< Indicates a SEARCH DATA command has satisfied an equal comparison.
140 SCSI_SENSE_VOLUME_OVERFLOW = 0x0d, ///< Indicates a buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium.
141 SCSI_SENSE_MISCOMPARE = 0x0e ///< ndicates that the source data did not match the data read from the medium.
142}scsi_sense_key_type_t;
143
144//--------------------------------------------------------------------+
145// SCSI Primary Command (SPC-4)
146//--------------------------------------------------------------------+
147
148/// SCSI Test Unit Ready Command
149typedef struct TU_ATTR_PACKED
150{
151 uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_TEST_UNIT_READY
152 uint8_t lun ; ///< Logical Unit
153 uint8_t reserved[3] ;
154 uint8_t control ;
155} scsi_test_unit_ready_t;
156
157TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct");
158
159/// SCSI Inquiry Command
160typedef struct TU_ATTR_PACKED
161{
162 uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_INQUIRY
163 uint8_t reserved1 ;
164 uint8_t page_code ;
165 uint8_t reserved2 ;
166 uint8_t alloc_length ; ///< specifies the maximum number of bytes that USB host has allocated in the Data-In Buffer. An allocation length of zero specifies that no data shall be transferred.
167 uint8_t control ;
168} scsi_inquiry_t, scsi_request_sense_t;
169
170TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct");
171
172/// SCSI Inquiry Response Data
173typedef struct TU_ATTR_PACKED
174{
175 uint8_t peripheral_device_type : 5;
176 uint8_t peripheral_qualifier : 3;
177
178 uint8_t : 7;
179 uint8_t is_removable : 1;
180
181 uint8_t version;
182
183 uint8_t response_data_format : 4;
184 uint8_t hierarchical_support : 1;
185 uint8_t normal_aca : 1;
186 uint8_t : 2;
187
188 uint8_t additional_length;
189
190 uint8_t protect : 1;
191 uint8_t : 2;
192 uint8_t third_party_copy : 1;
193 uint8_t target_port_group_support : 2;
194 uint8_t access_control_coordinator : 1;
195 uint8_t scc_support : 1;
196
197 uint8_t addr16 : 1;
198 uint8_t : 3;
199 uint8_t multi_port : 1;
200 uint8_t : 1; // vendor specific
201 uint8_t enclosure_service : 1;
202 uint8_t : 1;
203
204 uint8_t : 1; // vendor specific
205 uint8_t cmd_que : 1;
206 uint8_t : 2;
207 uint8_t sync : 1;
208 uint8_t wbus16 : 1;
209 uint8_t : 2;
210
211 uint8_t vendor_id[8] ; ///< 8 bytes of ASCII data identifying the vendor of the product.
212 uint8_t product_id[16]; ///< 16 bytes of ASCII data defined by the vendor.
213 uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor.
214} scsi_inquiry_resp_t;
215
216TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct");
217
218
219typedef struct TU_ATTR_PACKED
220{
221 uint8_t response_code : 7; ///< 70h - current errors, Fixed Format 71h - deferred errors, Fixed Format
222 uint8_t valid : 1;
223
224 uint8_t reserved;
225
226 uint8_t sense_key : 4;
227 uint8_t : 1;
228 uint8_t ili : 1; ///< Incorrect length indicator
229 uint8_t end_of_medium : 1;
230 uint8_t filemark : 1;
231
232 uint32_t information;
233 uint8_t add_sense_len;
234 uint32_t command_specific_info;
235 uint8_t add_sense_code;
236 uint8_t add_sense_qualifier;
237 uint8_t field_replaceable_unit_code;
238
239 uint8_t sense_key_specific[3]; ///< sense key specific valid bit is bit 7 of key[0], aka MSB in Big Endian layout
240
241} scsi_sense_fixed_resp_t;
242
243TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct");
244
245typedef struct TU_ATTR_PACKED
246{
247 uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_MODE_SENSE_6
248
249 uint8_t : 3;
250 uint8_t disable_block_descriptor : 1;
251 uint8_t : 4;
252
253 uint8_t page_code : 6;
254 uint8_t page_control : 2;
255
256 uint8_t subpage_code;
257 uint8_t alloc_length;
258 uint8_t control;
259} scsi_mode_sense6_t;
260
261TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct");
262
263// This is only a Mode parameter header(6).
264typedef struct TU_ATTR_PACKED
265{
266 uint8_t data_len;
267 uint8_t medium_type;
268
269 uint8_t reserved : 7;
270 bool write_protected : 1;
271
272 uint8_t block_descriptor_len;
273} scsi_mode_sense6_resp_t;
274
275TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct");
276
277typedef struct TU_ATTR_PACKED
278{
279 uint8_t cmd_code; ///< SCSI OpCode for \ref SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL
280 uint8_t reserved[3];
281 uint8_t prohibit_removal;
282 uint8_t control;
283} scsi_prevent_allow_medium_removal_t;
284
285TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct");
286
287typedef struct TU_ATTR_PACKED
288{
289 uint8_t cmd_code;
290
291 uint8_t immded : 1;
292 uint8_t : 7;
293
294 uint8_t TU_RESERVED;
295
296 uint8_t power_condition_mod : 4;
297 uint8_t : 4;
298
299 uint8_t start : 1;
300 uint8_t load_eject : 1;
301 uint8_t no_flush : 1;
302 uint8_t : 1;
303 uint8_t power_condition : 4;
304
305 uint8_t control;
306} scsi_start_stop_unit_t;
307
308TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct");
309
310//--------------------------------------------------------------------+
311// SCSI MMC
312//--------------------------------------------------------------------+
313/// SCSI Read Format Capacity: Write Capacity
314typedef struct TU_ATTR_PACKED
315{
316 uint8_t cmd_code;
317 uint8_t reserved[6];
318 uint16_t alloc_length;
319 uint8_t control;
320} scsi_read_format_capacity_t;
321
322TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct");
323
324typedef struct TU_ATTR_PACKED{
325 uint8_t reserved[3];
326 uint8_t list_length; /// must be 8*n, length in bytes of formattable capacity descriptor followed it.
327
328 uint32_t block_num; /// Number of Logical Blocks
329 uint8_t descriptor_type; // 00: reserved, 01 unformatted media , 10 Formatted media, 11 No media present
330
331 uint8_t reserved2;
332 uint16_t block_size_u16;
333
334} scsi_read_format_capacity_data_t;
335
336TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct");
337
338//--------------------------------------------------------------------+
339// SCSI Block Command (SBC-3)
340// NOTE: All data in SCSI command are in Big Endian
341//--------------------------------------------------------------------+
342
343/// SCSI Read Capacity 10 Command: Read Capacity
344typedef struct TU_ATTR_PACKED
345{
346 uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_READ_CAPACITY_10
347 uint8_t reserved1 ;
348 uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command
349 uint16_t reserved2 ;
350 uint8_t partial_medium_indicator ;
351 uint8_t control ;
352} scsi_read_capacity10_t;
353
354TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct");
355
356/// SCSI Read Capacity 10 Response Data
357typedef struct {
358 uint32_t last_lba ; ///< The last Logical Block Address of the device
359 uint32_t block_size ; ///< Block size in bytes
360} scsi_read_capacity10_resp_t;
361
362TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct");
363
364/// SCSI Read 10 Command
365typedef struct TU_ATTR_PACKED
366{
367 uint8_t cmd_code ; ///< SCSI OpCode
368 uint8_t reserved ; // has LUN according to wiki
369 uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command
370 uint8_t reserved2 ;
371 uint16_t block_count ; ///< Number of Blocks used by this command
372 uint8_t control ;
373} scsi_read10_t, scsi_write10_t;
374
375TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct");
376TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct");
377
378#ifdef __cplusplus
379 }
380#endif
381
382#endif /* _TUSB_MSC_H_ */