1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/include/usb/usbus/msc/scsi.h
Dylan Laduranty d49ed218ab usbus/msc: add initial support for Mass Storage Class
Signed-off-by: Dylan Laduranty <dylan.laduranty@mesotic.com>
2023-03-01 21:50:13 +01:00

296 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2019-2021 Mesotic SAS
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for
* more details.
*/
/**
* @ingroup usbus_msc
*
* @{
*
* @file
* @brief SCSI protocol definitions for USBUS
*
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
*/
#ifndef USB_USBUS_MSC_SCSI_H
#define USB_USBUS_MSC_SCSI_H
#include "byteorder.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef USBUS_MSC_VENDOR_ID
#define USBUS_MSC_VENDOR_ID "RIOT-OS"
#endif /* USBUS_MSC_VENDOR_ID */
#ifndef USBUS_MSC_PRODUCT_ID
#define USBUS_MSC_PRODUCT_ID "RIOT_MSC_DISK "
#endif /* USBUS_MSC_PRODUCT_ID */
#ifndef USBUS_MSC_PRODUCT_REV
#define USBUS_MSC_PRODUCT_REV " 1.0"
#endif /* USBUS_MSC_PRODUCT_REV */
/**
* @name USB SCSI Commands
*
* @see Table 9 - Packet Commands Supported by ATAPI Block Devices
* from INF-8070i draft published by SFF
* @{
*/
#define SCSI_TEST_UNIT_READY 0x00 /**< SCSI Test Unit Ready */
#define SCSI_REQUEST_SENSE 0x03 /**< SCSI Request Sense */
#define SCSI_FORMAT_UNIT 0x04 /**< SCSI Format Unit */
#define SCSI_INQUIRY 0x12 /**< SCSI Inquiry */
#define SCSI_MODE_SELECT6 0x15 /**< SCSI Mode Select6 */
#define SCSI_MODE_SENSE6 0x1A /**< SCSI Mode Sense6 */
#define SCSI_START_STOP_UNIT 0x1B /**< SCSI Start Stop Unit */
#define SCSI_MEDIA_REMOVAL 0x1E /**< SCSI Media Removal */
#define SCSI_READ_FORMAT_CAPACITIES 0x23 /**< SCSI Read Format Capacities */
#define SCSI_READ_CAPACITY 0x25 /**< SCSI Read Capacity */
#define SCSI_READ10 0x28 /**< SCSI Read10 */
#define SCCI_READ12 0xA8 /**< SCSI Read12 */
#define SCSI_WRITE10 0x2A /**< SCSI Write10 */
#define SCSI_WRITE12 0xAA /**< SCSI Write12 */
#define SCSI_SEEK 0x2B /**< SCSI Seek */
#define SCSI_WRITE_AND_VERIFY 0x2E /**< SCSI Write and Verify */
#define SCSI_VERIFY10 0x2F /**< SCSI Verify10 */
#define SCSI_MODE_SELECT10 0x55 /**< SCSI Mode Select10 */
#define SCSI_MODE_SENSE10 0x5A /**< SCSI Mode Sense10 */
/** @} */
/**
* @brief Command Block Wrapper signature
*/
#define SCSI_CBW_SIGNATURE 0x43425355
/**
* @brief Command Status Wrapper signature
*/
#define SCSI_CSW_SIGNATURE 0x53425355
/**
* @name USB SCSI Version list
* @{
*/
#define SCSI_VERSION_NONE 0x0000
#define SCSI_VERSION_SCSI1 0x0001
#define SCSI_VERSION_SCSI2 0x0002
/** @} */
/**
* @name USB SCSI Read format capacities descriptor type
*
* @see ( @ref msc_read_fmt_capa_pkt_t )
* @{
*/
#define SCSI_READ_FMT_CAPA_TYPE_RESERVED 0x00
#define SCSI_READ_FMT_CAPA_TYPE_UNFORMATTED 0x01
#define SCSI_READ_FMT_CAPA_TYPE_FORMATTED 0x02
#define SCSI_READ_FMT_CAPA_TYPE_NO_MEDIA 0x03
/** @} */
/**
* @brief SCSI Request Sense error type
*/
#define SCSI_REQUEST_SENSE_ERROR 0x70
/**
* @name USB SCSI Request Sense Sense Key type
*
* @{
*/
#define SCSI_SENSE_KEY_NO_SENSE 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
/** @} */
/**
* @brief Packet structure to answer (@ref SCSI_TEST_UNIT_READY) request
*
* @see Inquiry Command from SCSI Primary Command
*/
typedef struct __attribute__((packed)) {
uint8_t type; /**< type of device */
uint8_t logical_unit; /**< Selected LUN */
uint8_t reserved[10]; /**< Reserved */
} msc_test_unit_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_MODE_SELECT6) and
* (@ref SCSI_MODE_SENSE6) requests
*
* @see Inquiry Command from SCSI Primary Command
*/
typedef struct __attribute__((packed)) {
uint8_t mode_data_len; /**< Size of the whole packet */
uint8_t medium_type; /**< Type of medium */
uint8_t flags; /**< Miscellaneous flags */
uint8_t block_desc_len; /**< Length of block descriptor */
} msc_mode_parameter_pkt_t;
/**
* @brief CBW Packet structure for (@ref SCSI_READ10) and
* (@ref SCSI_WRITE10) requests
*
* @see Read10 or Write10 Command from SCSI Primary Command
*
* @warning uint16_t and uint32_t will be BIG ENDIAN
*/
typedef struct __attribute__((packed)) {
uint8_t opcode; /**< Operation code */
uint8_t flags; /**< Miscellaneous flags */
be_uint32_t blk_addr; /**< Block address */
uint8_t group_number; /**< Group number */
be_uint16_t xfer_len; /**< Transfer length in bytes */
} msc_cbw_rw10_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_INQUIRY) request
*
* @see Inquiry Command from SCSI Primary Command
*
* @note Vendor specific information (Byte 36 and above) and flags from bytes
* 5 to 7 are currently unsupported
*/
typedef struct __attribute__((packed)) {
uint8_t type; /**< Byte 0 Peripheral type */
uint8_t reserved1 : 7; /**< Byte 1 [B6..B0] Reserved */
uint8_t removable : 1; /**< Byte 1 [B7] Removable device flag */
uint8_t version; /**< Byte 2 SCSI Version */
uint8_t response_format : 4; /**< Byte 3 [B3..B0] Response Data Format */
uint8_t reserved3 : 4; /**< Byte 3 [B7..B4] Reserved */
uint8_t length; /**< Byte 4 Additional Length (n-4) */
uint8_t flags[3]; /**< Byte 7..5 Miscellaneous flags UNUSED BY USBUS ONLY */
uint8_t vendor_id[8]; /**< Byte 15..8 Vendor Identification */
uint8_t product_id[16]; /**< Byte 31..16 Product Identification */
uint8_t product_rev[4]; /**< Byte 35..32 Product Revision */
} msc_inquiry_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_READ_FORMAT_CAPACITIES) request
*
* @see READ FORMAT CAPACITIES from SCSI Multimedia Commands 2 (MMC-2)
*
*/
typedef struct __attribute__((packed)) {
uint8_t reserved1[3]; /**< Byte 2..0 reserved */
uint8_t list_length; /**< Byte 3 Capacity list length */
be_uint32_t blk_nb; /**< Byte 7..4 Number of blocks */
uint8_t type; /**< Byte 8 Descriptor type */
uint8_t blk_len[3]; /**< Byte 11..9 Block length */
} msc_read_fmt_capa_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_REQUEST_SENSE) request
*
*/
typedef struct __attribute__((packed)) {
uint8_t error_code; /**< Byte 0 Error code */
uint8_t reserved1; /**< Reserved */
uint8_t sense_key; /**< Byte 2 Sense key */
uint8_t reserved2[4]; /**< Byte 6..3 Information */
uint8_t add_len; /**< Byte 7 Additional sense length */
uint8_t reserved3[4]; /**< Byte 11..8 Vendor specific */
uint8_t asc; /**< Byte 12 Additional Sense Code */
uint8_t ascq; /**< Byte 13 Additional Sense Code Qualifier */
uint8_t fruc; /**< Byte 14 Field Replaceable Unit Code */
uint16_t sk_spec; /**< Byte 16..15 Sense Key Specific */
} msc_request_sense_pkt_t;
/**
* @brief Packet structure to answer (@ref SCSI_READ_CAPACITY) request
*
* @note Multiply the two values from this struct between them
* indicates the total size of your MTD device
*
* @see Read Capacities from SCSI Primary Command
*/
typedef struct __attribute__((packed)) {
be_uint32_t last_blk; /**< Indicate last block number */
be_uint32_t blk_len; /**< Total size of a block in bytes */
} msc_read_capa_pkt_t;
/**
* @brief Command Block Wrapper packet structure
*
* @see Table 5.1 Command Block Wrapper (CBW)
* from Universal Serial Bus Mass Storage Class Bulk-Only Transport
*/
typedef struct __attribute__((packed)) {
uint32_t signature; /**< CBW signature (@ref SCSI_CBW_SIGNATURE) */
uint32_t tag; /**< ID for the current command */
uint32_t data_len; /**< Number of bytes host expects to transfer from/to */
uint8_t flags; /**< Command block flags */
uint8_t lun; /**< Target Logical Unit Number */
uint8_t cb_len; /**< Length of the block in bytes (max: 16 bytes) */
uint8_t cb[16]; /**< Command block buffer */
} msc_cbw_buf_t;
/**
* @brief Command Status Wrapper packet structure
*
* @see Table 5.2 - Command Status Wrapper
* from Universal Serial Bus Mass Storage Class Bulk-Only Transport
*/
typedef struct __attribute__((packed)) {
uint32_t signature; /**< CSW signature (@ref SCSI_CSW_SIGNATURE) */
uint32_t tag; /**< ID for the answered CBW */
uint32_t data_left; /**< Indicate how many bytes from the CBW were not processed */
uint8_t status; /**< Status of the command */
} msc_csw_buf_t;
/**
* @brief USBUS Command Block Wrapper information
*
*/
typedef struct {
uint32_t tag; /**< Store tag information from CBW */
size_t len; /**< Remaining bytes to handle */
uint8_t status; /**< Status of the current operation */
uint8_t lun; /**< Store LUN from CBW */
} cbw_info_t;
/**
* @brief Process incoming Command Block Wrapper buffer
*
* @param usbus USBUS thread to use
* @param handler MSC device struct
* @param ep Endpoint pointer to read CBW from
* @param len Size of the received CBW buffer
*/
void usbus_msc_scsi_process_cmd(usbus_t *usbus, usbus_handler_t *handler, usbdev_ep_t *ep,
size_t len);
/**
* @brief Generate Command Status Wrapper and send it to the host
*
* @param handler MSC device struct
* @param cmd struct containing needed information to generate CBW response
*/
void scsi_gen_csw(usbus_handler_t *handler, cbw_info_t *cmd);
#ifdef __cplusplus
}
#endif
#endif /* USB_USBUS_MSC_SCSI_H */
/** @} */