123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /* Copyright (C) 2015-2016 Andrew J. Kroll
- and
- Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- Contact information
- -------------------
-
- Circuits At Home, LTD
- Web : http://www.circuitsathome.com
- e-mail : support@circuitsathome.com
- */
-
- #ifndef __UHS_BULK_STORAGE_H__
- #define __UHS_BULK_STORAGE_H__
-
-
- ////////////////////////////////////////////////////////////////////////////////
- // Define any of these options at the top of your sketch to override
- // the defaults contained herewith. Do NOT do modifications here.
- // Macro | Settings and notes | Default
- // -----------------------------------------+-----------------------+-----------
- // | 1 to 8 |
- // | Each LUN needs |
- // MASS_MAX_SUPPORTED_LUN | ~13 bytes to be able | 8
- // | to track the state of |
- // | each unit. |
- // -----------------------------------------+-----------------------+-----------
- // | Just define to use. |
- // DEBUG_PRINTF_EXTRA_HUGE_UHS_BULK_STORAGE | works only if extra |
- // | huge debug is on too. |
- // -----------------------------------------^-----------------------^-----------
-
- #ifndef MASS_MAX_SUPPORTED_LUN
- #define MASS_MAX_SUPPORTED_LUN 8
- #endif
-
- #include "UHS_SCSI.h"
-
- #define UHS_BULK_bmREQ_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
- #define UHS_BULK_bmREQ_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
-
- // Request Codes
- #define UHS_BULK_REQ_ADSC 0x00U
- #define UHS_BULK_REQ_GET 0xFCU
- #define UHS_BULK_REQ_PUT 0xFDU
- #define UHS_BULK_REQ_GET_MAX_LUN 0xFEU
- #define UHS_BULK_REQ_BOMSR 0xFFU // Mass Storage Reset
-
- #define UHS_BULK_CBW_SIGNATURE 0x43425355LU
- #define UHS_BULK_CSW_SIGNATURE 0x53425355LU
-
- #define UHS_BULK_CMD_DIR_OUT 0x00U
- #define UHS_BULK_CMD_DIR_IN 0x80U
-
- /* Bulk error codes */
- #define UHS_BULK_ERR_SUCCESS UHS_HOST_ERROR_NONE
- #define UHS_BULK_ERR_PHASE_ERROR 0x22U
- #define UHS_BULK_ERR_UNIT_NOT_READY 0x23U
- #define UHS_BULK_ERR_UNIT_BUSY 0x24U
- #define UHS_BULK_ERR_STALL 0x25U
- #define UHS_BULK_ERR_CMD_NOT_SUPPORTED 0x26U
- #define UHS_BULK_ERR_INVALID_CSW 0x27U
- #define UHS_BULK_ERR_NO_MEDIA 0x28U
- #define UHS_BULK_ERR_BAD_LBA 0x29U
- #define UHS_BULK_ERR_MEDIA_CHANGED 0x2AU
- #define UHS_BULK_ERR_DEVICE_DISCONNECTED UHS_HOST_ERROR_UNPLUGGED
- #define UHS_BULK_ERR_UNABLE_TO_RECOVER 0x32U // Reset recovery error
- #define UHS_BULK_ERR_INVALID_LUN 0x33U
- #define UHS_BULK_ERR_WRITE_STALL 0x34U
- #define UHS_BULK_ERR_READ_NAKS 0x35U
- #define UHS_BULK_ERR_WRITE_NAKS 0x36U
- #define UHS_BULK_ERR_WRITE_PROTECTED 0x37U
- #define UHS_BULK_ERR_NOT_IMPLEMENTED 0xFDU
- #define UHS_BULK_ERR_GENERAL_SCSI_ERROR 0xF0U
- #define UHS_BULK_ERR_GENERAL_USB_ERROR 0xFFU
- #define UHS_BULK_ERR_USER 0xA0U // For subclasses to define their own error codes
-
- #define MASS_MAX_ENDPOINTS 3
-
- struct UHS_BULK_CommandBlockWrapperBase {
- volatile uint32_t dCBWSignature;
- volatile uint32_t dCBWTag;
- volatile uint32_t dCBWDataTransferLength;
- volatile uint8_t bmCBWFlags;
- public:
-
- UHS_BULK_CommandBlockWrapperBase() {
- }
-
- UHS_BULK_CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) :
- dCBWSignature(UHS_BULK_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) {
- }
- } __attribute__((packed));
-
- struct UHS_BULK_CommandBlockWrapper : public UHS_BULK_CommandBlockWrapperBase {
-
- struct {
- uint8_t bmCBWLUN : 4;
- uint8_t bmReserved1 : 4;
- };
-
- struct {
- uint8_t bmCBWCBLength : 4;
- uint8_t bmReserved2 : 4;
- };
-
- uint8_t CBWCB[16];
-
- public:
- // All zeroed.
-
- UHS_BULK_CommandBlockWrapper() :
- UHS_BULK_CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) {
- for(int i = 0; i < 16; i++) CBWCB[i] = 0;
- }
-
- // Generic Wrap, CDB zeroed.
-
- UHS_BULK_CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) :
- UHS_BULK_CommandBlockWrapperBase(tag, xflen, flgs),
- bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) {
- for(int i = 0; i < 16; i++) CBWCB[i] = 0;
- SCSI_CDB_BASE_t *x = reinterpret_cast<SCSI_CDB_BASE_t *>(CBWCB);
- x->LUN = cmd;
- }
-
- // Wrap for CDB of 6
-
- UHS_BULK_CommandBlockWrapper(uint32_t tag, uint32_t xflen, SCSI_CDB6_t *cdb, uint8_t dir) :
- UHS_BULK_CommandBlockWrapperBase(tag, xflen, dir),
- bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) {
- memcpy(&CBWCB, cdb, 6);
- }
- // Wrap for CDB of 10
-
- UHS_BULK_CommandBlockWrapper(uint32_t tag, uint32_t xflen, SCSI_CDB10_t *cdb, uint8_t dir) :
- UHS_BULK_CommandBlockWrapperBase(tag, xflen, dir),
- bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) {
- memcpy(&CBWCB, cdb, 10);
- }
- } __attribute__((packed));
-
- struct UHS_BULK_CommandStatusWrapper {
- uint32_t dCSWSignature;
- uint32_t dCSWTag;
- uint32_t dCSWDataResidue;
- uint8_t bCSWStatus;
- } __attribute__((packed));
-
- class UHS_Bulk_Storage : public UHS_USBInterface {
- protected:
- static const uint8_t epDataInIndex = 1; // DataIn endpoint index
- static const uint8_t epDataOutIndex = 2; // DataOUT endpoint index
- static const uint8_t epInterruptInIndex = 3; // InterruptIN endpoint index
-
- uint8_t bMaxLUN; // Max LUN
- volatile uint32_t dCBWTag; // Tag
- volatile uint8_t bTheLUN; // Active LUN
- volatile uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors
- volatile uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits
- volatile bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes.
- volatile bool WriteOk[MASS_MAX_SUPPORTED_LUN];
- void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
-
- public:
- UHS_Bulk_Storage(UHS_USB_HOST_BASE *p);
-
- volatile UHS_EpInfo epInfo[MASS_MAX_ENDPOINTS];
-
- uint8_t GetbMaxLUN() {
- return bMaxLUN; // Max LUN
- }
-
- uint8_t GetbTheLUN() {
- return bTheLUN; // Active LUN
- }
-
- bool WriteProtected(uint8_t lun);
- uint8_t MediaCTL(uint8_t lun, uint8_t ctl);
- uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
- uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
- uint8_t LockMedia(uint8_t lun, uint8_t lock);
-
- bool LUNIsGood(uint8_t lun);
- uint32_t GetCapacity(uint8_t lun);
- uint16_t GetSectorSize(uint8_t lun);
- uint8_t SCSITransaction6(SCSI_CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
- uint8_t SCSITransaction10(SCSI_CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
-
-
- // Configure and internal methods, these should never be called by a user's sketch.
- uint8_t Start();
- bool OKtoEnumerate(ENUMERATION_INFO *ei);
- uint8_t SetInterface(ENUMERATION_INFO *ei);
-
- uint8_t GetAddress() {
- return bAddress;
- };
-
-
- void Poll();
-
- void DriverDefaults();
-
-
- private:
- void Reset();
- void CheckMedia();
-
- bool IsValidCBW(uint8_t size, uint8_t *pcbw);
- bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);
- bool IsValidCSW(UHS_BULK_CommandStatusWrapper *pcsw, UHS_BULK_CommandBlockWrapperBase *pcbw);
-
- bool CheckLUN(uint8_t lun);
-
- uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
- uint8_t TestUnitReady(uint8_t lun);
- uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);
- uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf);
- uint8_t GetMaxLUN(uint8_t *max_lun);
- uint8_t SetCurLUN(uint8_t lun);
- uint8_t ResetRecovery();
- uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf);
- uint8_t Page3F(uint8_t lun);
- uint8_t ClearEpHalt(uint8_t index);
- uint8_t Transaction(UHS_BULK_CommandBlockWrapper *cbw, uint16_t bsize, void *buf);
- uint8_t HandleUsbError(uint8_t error, uint8_t index);
- uint8_t HandleSCSIError(uint8_t status);
-
- };
-
- #if defined(LOAD_UHS_BULK_STORAGE) && !defined(UHS_BULK_STORAGE_LOADED)
- #include "UHS_BULK_STORAGE_INLINE.h"
- #endif
- #endif // __MASSTORAGE_H__
|