/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 2011,2012,2013 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. ChibiOS/RT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _USB_MSD_H_ #define _USB_MSD_H_ #include "hal.h" /* Default to disabled for USB Mass Storage */ #if !defined(HAL_USE_MASS_STORAGE_USB) # define HAL_USE_MASS_STORAGE_USB TRUE #endif #if HAL_USE_MASS_STORAGE_USB || defined(__DOXYGEN__) #if 0 #define MSD_RW_LED_ON() palSetPad(GPIOI, GPIOI_TRI_LED_BLUE) #define MSD_RW_LED_OFF() palClearPad(GPIOI, GPIOI_TRI_LED_BLUE) #define MSD_R_LED_ON() palSetPad(GPIOI, GPIOI_TRI_LED_BLUE) #define MSD_R_LED_OFF() palClearPad(GPIOI, GPIOI_TRI_LED_BLUE) #define MSD_W_LED_ON() palSetPad(GPIOH, GPIOI_TRI_LED_BLUE) #define MSD_W_LED_OFF() palClearPad(GPIOH, GPIOI_TRI_LED_BLUE) #else #define MSD_RW_LED_ON() #define MSD_RW_LED_OFF() #define MSD_R_LED_ON() #define MSD_R_LED_OFF() #define MSD_W_LED_ON() #define MSD_W_LED_OFF() #endif #if STM32_USB_USE_OTG2 && STM32_USE_USB_OTG2_HS # define USB_MS_EP_SIZE 512 #else # define USB_MS_EP_SIZE 64 #endif #define MSD_THREAD_STACK_SIZE 1024 #define MSD_REQ_RESET 0xFF #define MSD_GET_MAX_LUN 0xFE #define MSD_CBW_SIGNATURE 0x43425355 #define MSD_CSW_SIGNATURE 0x53425355 #define MSD_COMMAND_DIR_DATA_OUT (0 << 7) #define MSD_COMMAND_DIR_DATA_IN (1 << 7) #define MSD_SETUP_WORD(setup, index) (uint16_t)(((uint16_t)setup[index+1] << 8) | (setup[index] & 0x00FF)) #define MSD_SETUP_VALUE(setup) MSD_SETUP_WORD(setup, 2) #define MSD_SETUP_INDEX(setup) MSD_SETUP_WORD(setup, 4) #define MSD_SETUP_LENGTH(setup) MSD_SETUP_WORD(setup, 6) typedef enum { SCSI_CMD_TEST_UNIT_READY = 0x00, SCSI_CMD_REQUEST_SENSE_6 = 0x03, SCSI_CMD_INQUIRY = 0x12, SCSI_CMD_MODE_SENSE_6 = 0x1A, SCSI_CMD_START_STOP_UNIT = 0x1B, SCSI_CMD_SEND_DIAGNOSTIC = 0x1D, SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, SCSI_CMD_READ_CAPACITY_10 = 0x25, SCSI_CMD_READ_10 = 0x28, SCSI_CMD_WRITE_10 = 0x2A, SCSI_CMD_VERIFY_10 = 0x2F, SCSI_CMD_SYNCHRONIZE_CACHE_10 = 0x35, } msd_scsi_command_t; #define MSD_COMMAND_PASSED 0x00 #define MSD_COMMAND_FAILED 0x01 #define MSD_COMMAND_PHASE_ERROR 0x02 #define SCSI_SENSE_KEY_GOOD 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_COPY_ABORTED 0x0A #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D #define SCSI_SENSE_KEY_MISCOMPARE 0x0E #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00 #define SCSI_ASENSE_PEREPHERIAL_DEVICE_WRITE_FAULT 0x03 #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04 #define SCSI_ASENSE_UNRECOVERED_READ_ERROR 0x11 #define SCSI_ASENSE_INVALID_COMMAND 0x20 #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21 #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24 #define SCSI_ASENSE_WRITE_PROTECTED 0x27 #define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28 #define SCSI_ASENSE_FORMAT_ERROR 0x31 #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A #define SCSI_ASENSEQ_NO_QUALIFIER 0x00 #define SCSI_ASENSEQ_PEREPHERIAL_DEVICE_WRITE_FAULT 0x00 #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01 #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02 #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07 PACK_STRUCT_BEGIN typedef struct { uint32_t signature; uint32_t tag; uint32_t data_len; uint8_t flags; uint8_t lun; uint8_t scsi_cmd_len; uint8_t scsi_cmd_data[16]; } PACK_STRUCT_STRUCT msd_cbw_t PACK_STRUCT_END; PACK_STRUCT_BEGIN typedef struct { uint32_t signature; uint32_t tag; uint32_t data_residue; uint8_t status; } PACK_STRUCT_STRUCT msd_csw_t PACK_STRUCT_END; typedef struct { uint8_t byte[18]; } PACK_STRUCT_STRUCT scsi_sense_response_t; typedef struct { uint8_t mode_data_length; //Number of bytes that follow uint8_t medium_type; //0x00 for SBC devices uint8_t device_specifc_paramters; //bit 7 is the write protect bit uint8_t block_descriptor_length; //Length in bytes of all block descriptors in the mode parameter list. } PACK_STRUCT_STRUCT scsi_mode_sense6_response_t; PACK_STRUCT_BEGIN typedef struct { uint8_t peripheral; uint8_t removable; uint8_t version; uint8_t response_data_format; uint8_t additional_length; uint8_t sccstp; uint8_t bqueetc; uint8_t cmdque; uint8_t vendorID[8]; uint8_t productID[16]; uint8_t productRev[4]; } PACK_STRUCT_STRUCT scsi_inquiry_response_t PACK_STRUCT_END; PACK_STRUCT_BEGIN typedef struct { uint8_t payload_byte_length[4]; uint32_t last_block_addr; uint32_t block_size; } PACK_STRUCT_STRUCT scsi_read_format_capacity_response_t PACK_STRUCT_END; PACK_STRUCT_BEGIN typedef struct { uint32_t last_block_addr; uint32_t block_size; } PACK_STRUCT_STRUCT scsi_read_capacity10_response_t PACK_STRUCT_END; PACK_STRUCT_BEGIN typedef struct { uint8_t op_code; uint8_t lun_immed; uint8_t res1; uint8_t res2; uint8_t loej_start; uint8_t control; } PACK_STRUCT_STRUCT scsi_start_stop_unit_request_t; typedef enum { MSD_WAIT_MODE_NONE = 0, MSD_WAIT_MODE_BULK_IN, MSD_WAIT_MODE_BULK_OUT } msd_wait_mode_t; typedef enum { MSD_STATE_IDLE = 0, MSD_STATE_READ_CMD_BLOCK, MSD_STATE_EJECTED } msd_state_t; typedef enum { USB_MSD_DRIVER_UNINITIALIZED = 0, USB_MSD_DRIVER_ERROR, USB_MSD_DRIVER_OK, USB_MSD_DRIVER_STOPPED, USB_MSD_DRIVER_ERROR_BLK_DEV_NOT_READY, } usb_msd_driver_state_t; typedef struct USBMassStorageDriver USBMassStorageDriver; struct USBMassStorageDriver { /* Driver Setup Data */ USBDriver *usbp; BaseBlockDevice *bbdp; EventSource evt_connected; EventSource evt_ejected; BlockDeviceInfo block_dev_info; bool block_dev_info_valid_flag; usb_msd_driver_state_t driver_state; usbep_t ms_ep_number; uint16_t msd_interface_number; bool_t (*enable_msd_callback)(void); bool_t (*suspend_threads_callback)(void); /* Externally modifiable settings */ bool_t enable_media_removial; bool_t disable_usb_bus_disconnect_on_eject; BaseSequentialStream *chp; /*For debug logging*/ /*Internal data for operation of the driver */ BinarySemaphore bsem; BinarySemaphore usb_transfer_thread_bsem; BinarySemaphore mass_sorage_thd_bsem; volatile uint32_t trigger_transfer_index; volatile bool_t bulk_in_interupt_flag; volatile bool_t bulk_out_interupt_flag; struct { scsi_read_format_capacity_response_t format_capacity_response; scsi_read_capacity10_response_t read_capacity10_response; scsi_mode_sense6_response_t mode_sense6_response; uint8_t max_lun_len_buf[1]; scsi_inquiry_response_t scsi_inquiry_response; } data; msd_state_t state; msd_cbw_t cbw; msd_csw_t csw; scsi_sense_response_t sense; volatile bool_t reconfigured_or_reset_event; bool_t command_succeeded_flag; bool_t stall_in_endpoint; bool_t stall_out_endpoint; /*Debugging Information*/ volatile uint32_t read_error_count; volatile uint32_t write_error_count; volatile uint32_t read_success_count; volatile uint32_t write_success_count; char *msd_thread_state; char *transfer_thread_state; char *scsi_command_state; volatile uint8_t last_bad_scsi_command; /* Externally readable values */ volatile bool_t debug_enable_msd; volatile msd_wait_mode_t debug_wait_for_isr; WORKING_AREA(waMassStorage, MSD_THREAD_STACK_SIZE); WORKING_AREA(waMassStorageUSBTransfer, MSD_THREAD_STACK_SIZE); }; #ifdef __cplusplus extern "C" { #endif usb_msd_driver_state_t msdInit(USBDriver *usbp, BaseBlockDevice *bbdp, USBMassStorageDriver *msdp, const usbep_t ms_ep_number, const uint16_t msd_interface_number); usb_msd_driver_state_t msdStart(USBMassStorageDriver *msdp); usb_msd_driver_state_t msdStop(USBMassStorageDriver *msdp); void msdBulkInCallbackComplete(USBDriver *usbp, usbep_t ep); void msdBulkOutCallbackComplete(USBDriver *usbp, usbep_t ep); bool_t msdRequestsHook(USBDriver *usbp); bool_t msdRequestsHook2(USBDriver *usbp, USBMassStorageDriver *msdp); const char* usb_msd_driver_state_t_to_str(const usb_msd_driver_state_t driver_state); #ifdef __cplusplus } #endif #endif /* HAL_USE_MASS_STORAGE_USB */ #endif /* _USB_MSD_H_ */