Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers masstorage.h Source File

masstorage.h

00001 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
00002 
00003 This program is free software; you can redistribute it and/or modify
00004 it under the terms of the GNU General Public License as published by
00005 the Free Software Foundation; either version 2 of the License, or
00006 (at your option) any later version.
00007 
00008 This program is distributed in the hope that it will be useful,
00009 but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License
00014 along with this program; if not, write to the Free Software
00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 
00017 Contact information
00018 -------------------
00019 
00020 Circuits At Home, LTD
00021 Web      :  http://www.circuitsathome.com
00022 e-mail   :  support@circuitsathome.com
00023  */
00024 
00025 #if !defined(__MASSTORAGE_H__)
00026 #define __MASSTORAGE_H__
00027 
00028 // Cruft removal, makes driver smaller, faster.
00029 #ifndef MS_WANT_PARSER
00030 #define MS_WANT_PARSER 0
00031 #endif
00032 
00033 #include "Usb.h"
00034 
00035 #define bmREQ_MASSOUT       USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
00036 #define bmREQ_MASSIN        USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
00037 
00038 // Mass Storage Subclass Constants
00039 #define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00    // De facto use
00040 #define MASS_SUBCLASS_RBC               0x01
00041 #define MASS_SUBCLASS_ATAPI             0x02    // MMC-5 (ATAPI)
00042 #define MASS_SUBCLASS_OBSOLETE1         0x03    // Was QIC-157
00043 #define MASS_SUBCLASS_UFI               0x04    // Specifies how to interface Floppy Disk Drives to USB
00044 #define MASS_SUBCLASS_OBSOLETE2         0x05    // Was SFF-8070i
00045 #define MASS_SUBCLASS_SCSI              0x06    // SCSI Transparent Command Set
00046 #define MASS_SUBCLASS_LSDFS             0x07    // Specifies how host has to negotiate access before trying SCSI
00047 #define MASS_SUBCLASS_IEEE1667          0x08
00048 
00049 // Mass Storage Class Protocols
00050 #define MASS_PROTO_CBI                  0x00    // CBI (with command completion interrupt)
00051 #define MASS_PROTO_CBI_NO_INT           0x01    // CBI (without command completion interrupt)
00052 #define MASS_PROTO_OBSOLETE             0x02
00053 #define MASS_PROTO_BBB                  0x50    // Bulk Only Transport
00054 #define MASS_PROTO_UAS                  0x62
00055 
00056 // Request Codes
00057 #define MASS_REQ_ADSC                   0x00
00058 #define MASS_REQ_GET                    0xFC
00059 #define MASS_REQ_PUT                    0xFD
00060 #define MASS_REQ_GET_MAX_LUN            0xFE
00061 #define MASS_REQ_BOMSR                  0xFF    // Bulk-Only Mass Storage Reset
00062 
00063 #define MASS_CBW_SIGNATURE              0x43425355
00064 #define MASS_CSW_SIGNATURE              0x53425355
00065 
00066 #define MASS_CMD_DIR_OUT                0 // (0 << 7)
00067 #define MASS_CMD_DIR_IN                 0x80 //(1 << 7)
00068 
00069 /*
00070  * Reference documents from T10 (http://www.t10.org)
00071  * SCSI Primary Commands - 3 (SPC-3)
00072  * SCSI Block Commands - 2 (SBC-2)
00073  * Multi-Media Commands - 5 (MMC-5)
00074  */
00075 
00076 /* Group 1 commands (CDB's here are should all be 6-bytes) */
00077 #define SCSI_CMD_TEST_UNIT_READY        0x00
00078 #define SCSI_CMD_REQUEST_SENSE          0x03
00079 #define SCSI_CMD_FORMAT_UNIT            0x04
00080 #define SCSI_CMD_READ_6                 0x08
00081 #define SCSI_CMD_WRITE_6                0x0A
00082 #define SCSI_CMD_INQUIRY                0x12
00083 #define SCSI_CMD_MODE_SELECT_6          0x15
00084 #define SCSI_CMD_MODE_SENSE_6           0x1A
00085 #define SCSI_CMD_START_STOP_UNIT        0x1B
00086 #define SCSI_CMD_PREVENT_REMOVAL        0x1E
00087 /* Group 2 Commands (CDB's here are 10-bytes) */
00088 #define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
00089 #define SCSI_CMD_READ_CAPACITY_10       0x25
00090 #define SCSI_CMD_READ_10                0x28
00091 #define SCSI_CMD_WRITE_10               0x2A
00092 #define SCSI_CMD_SEEK_10                0x2B
00093 #define SCSI_CMD_ERASE_10               0x2C
00094 #define SCSI_CMD_WRITE_AND_VERIFY_10    0x2E
00095 #define SCSI_CMD_VERIFY_10              0x2F
00096 #define SCSI_CMD_SYNCHRONIZE_CACHE      0x35
00097 #define SCSI_CMD_WRITE_BUFFER           0x3B
00098 #define SCSI_CMD_READ_BUFFER            0x3C
00099 #define SCSI_CMD_READ_SUBCHANNEL        0x42
00100 #define SCSI_CMD_READ_TOC               0x43
00101 #define SCSI_CMD_READ_HEADER            0x44
00102 #define SCSI_CMD_PLAY_AUDIO_10          0x45
00103 #define SCSI_CMD_GET_CONFIGURATION      0x46
00104 #define SCSI_CMD_PLAY_AUDIO_MSF         0x47
00105 #define SCSI_CMD_PLAY_AUDIO_TI          0x48
00106 #define SCSI_CMD_PLAY_TRACK_REL_10      0x49
00107 #define SCSI_CMD_GET_EVENT_STATUS       0x4A
00108 #define SCSI_CMD_PAUSE_RESUME           0x4B
00109 #define SCSI_CMD_READ_DISC_INFORMATION  0x51
00110 #define SCSI_CMD_READ_TRACK_INFORMATION 0x52
00111 #define SCSI_CMD_RESERVE_TRACK          0x53
00112 #define SCSI_CMD_SEND_OPC_INFORMATION   0x54
00113 #define SCSI_CMD_MODE_SELECT_10         0x55
00114 #define SCSI_CMD_REPAIR_TRACK           0x58
00115 #define SCSI_CMD_MODE_SENSE_10          0x5A
00116 #define SCSI_CMD_CLOSE_TRACK_SESSION    0x5B
00117 #define SCSI_CMD_READ_BUFFER_CAPACITY   0x5C
00118 #define SCSI_CMD_SEND_CUE_SHEET         0x5D
00119 /* Group 5 Commands (CDB's here are 12-bytes) */
00120 #define SCSI_CMD_REPORT_LUNS            0xA0
00121 #define SCSI_CMD_BLANK                  0xA1
00122 #define SCSI_CMD_SECURITY_PROTOCOL_IN   0xA2
00123 #define SCSI_CMD_SEND_KEY               0xA3
00124 #define SCSI_CMD_REPORT_KEY             0xA4
00125 #define SCSI_CMD_PLAY_AUDIO_12          0xA5
00126 #define SCSI_CMD_LOAD_UNLOAD            0xA6
00127 #define SCSI_CMD_SET_READ_AHEAD         0xA7
00128 #define SCSI_CMD_READ_12                0xA8
00129 #define SCSI_CMD_PLAY_TRACK_REL_12      0xA9
00130 #define SCSI_CMD_WRITE_12               0xAA
00131 #define SCSI_CMD_READ_MEDIA_SERIAL_12   0xAB
00132 #define SCSI_CMD_GET_PERFORMANCE        0xAC
00133 #define SCSI_CMD_READ_DVD_STRUCTURE     0xAD
00134 #define SCSI_CMD_SECURITY_PROTOCOL_OUT  0xB5
00135 #define SCSI_CMD_SET_STREAMING          0xB6
00136 #define SCSI_CMD_READ_MSF               0xB9
00137 #define SCSI_CMD_SET_SPEED              0xBB
00138 #define SCSI_CMD_MECHANISM_STATUS       0xBD
00139 #define SCSI_CMD_READ_CD                0xBE
00140 #define SCSI_CMD_SEND_DISC_STRUCTURE    0xBF
00141 /* Vendor-unique Commands, included for completeness */
00142 #define SCSI_CMD_CD_PLAYBACK_STATUS     0xC4 /* SONY unique */
00143 #define SCSI_CMD_PLAYBACK_CONTROL       0xC9 /* SONY unique */
00144 #define SCSI_CMD_READ_CDDA              0xD8 /* Vendor unique */
00145 #define SCSI_CMD_READ_CDXA              0xDB /* Vendor unique */
00146 #define SCSI_CMD_READ_ALL_SUBCODES      0xDF /* Vendor unique */
00147 
00148 /* SCSI error codes */
00149 #define SCSI_S_NOT_READY                0x02
00150 #define SCSI_S_MEDIUM_ERROR             0x03
00151 #define SCSI_S_ILLEGAL_REQUEST          0x05
00152 #define SCSI_S_UNIT_ATTENTION           0x06
00153 #define SCSI_ASC_LBA_OUT_OF_RANGE       0x21
00154 #define SCSI_ASC_MEDIA_CHANGED          0x28
00155 #define SCSI_ASC_MEDIUM_NOT_PRESENT     0x3A
00156 
00157 /* USB error codes */
00158 #define MASS_ERR_SUCCESS                0x00
00159 #define MASS_ERR_PHASE_ERROR            0x02
00160 #define MASS_ERR_UNIT_NOT_READY         0x03
00161 #define MASS_ERR_UNIT_BUSY              0x04
00162 #define MASS_ERR_STALL                  0x05
00163 #define MASS_ERR_CMD_NOT_SUPPORTED      0x06
00164 #define MASS_ERR_INVALID_CSW            0x07
00165 #define MASS_ERR_NO_MEDIA               0x08
00166 #define MASS_ERR_BAD_LBA                0x09
00167 #define MASS_ERR_MEDIA_CHANGED          0x0A
00168 #define MASS_ERR_DEVICE_DISCONNECTED    0x11
00169 #define MASS_ERR_UNABLE_TO_RECOVER      0x12    // Reset recovery error
00170 #define MASS_ERR_INVALID_LUN            0x13
00171 #define MASS_ERR_WRITE_STALL            0x14
00172 #define MASS_ERR_READ_NAKS              0x15
00173 #define MASS_ERR_WRITE_NAKS             0x16
00174 #define MASS_ERR_WRITE_PROTECTED        0x17
00175 #define MASS_ERR_NOT_IMPLEMENTED        0xFD
00176 #define MASS_ERR_GENERAL_SCSI_ERROR     0xFE
00177 #define MASS_ERR_GENERAL_USB_ERROR      0xFF
00178 #define MASS_ERR_USER                   0xA0    // For subclasses to define their own error codes
00179 
00180 #define MASS_TRANS_FLG_CALLBACK         0x01    // Callback is involved
00181 #define MASS_TRANS_FLG_NO_STALL_CHECK   0x02    // STALL condition is not checked
00182 #define MASS_TRANS_FLG_NO_PHASE_CHECK   0x04    // PHASE_ERROR is not checked
00183 
00184 #define MASS_MAX_ENDPOINTS              3
00185 
00186 struct Capacity {
00187         uint8_t data[8];
00188         //uint32_t dwBlockAddress;
00189         //uint32_t dwBlockLength;
00190 } __attribute__((packed));
00191 
00192 struct BASICCDB {
00193         uint8_t Opcode;
00194 
00195         unsigned unused : 5;
00196         unsigned LUN : 3;
00197 
00198         uint8_t info[12];
00199 } __attribute__((packed));
00200 
00201 typedef BASICCDB BASICCDB_t;
00202 
00203 struct CDB6 {
00204         uint8_t Opcode;
00205 
00206         unsigned LBAMSB : 5;
00207         unsigned LUN : 3;
00208 
00209         uint8_t LBAHB;
00210         uint8_t LBALB;
00211         uint8_t AllocationLength;
00212         uint8_t Control;
00213 
00214 public:
00215 
00216         CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) :
00217         Opcode(_Opcode), LBAMSB(BGRAB2(LBA) & 0x1f), LUN(_LUN), LBAHB(BGRAB1(LBA)), LBALB(BGRAB0(LBA)),
00218         AllocationLength(_AllocationLength), Control(_Control) {
00219         }
00220 
00221         CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) :
00222         Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0),
00223         AllocationLength(_AllocationLength), Control(_Control) {
00224         }
00225 } __attribute__((packed));
00226 
00227 typedef CDB6 CDB6_t;
00228 
00229 struct CDB10 {
00230         uint8_t Opcode;
00231 
00232         unsigned Service_Action : 5;
00233         unsigned LUN : 3;
00234 
00235         uint8_t LBA_L_M_MB;
00236         uint8_t LBA_L_M_LB;
00237         uint8_t LBA_L_L_MB;
00238         uint8_t LBA_L_L_LB;
00239 
00240         uint8_t Misc2;
00241 
00242         uint8_t ALC_MB;
00243         uint8_t ALC_LB;
00244 
00245         uint8_t Control;
00246 public:
00247 
00248         CDB10(uint8_t _Opcode, uint8_t _LUN) :
00249         Opcode(_Opcode), Service_Action(0), LUN(_LUN),
00250         LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0),
00251         Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) {
00252         }
00253 
00254         CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) :
00255         Opcode(_Opcode), Service_Action(0), LUN(_LUN),
00256         LBA_L_M_MB(BGRAB3(_LBA)), LBA_L_M_LB(BGRAB2(_LBA)), LBA_L_L_MB(BGRAB1(_LBA)), LBA_L_L_LB(BGRAB0(_LBA)),
00257         Misc2(0), ALC_MB(BGRAB1(xflen)), ALC_LB(BGRAB0(xflen)), Control(0) {
00258         }
00259 } __attribute__((packed));
00260 
00261 typedef CDB10 CDB10_t;
00262 
00263 struct CDB12 {
00264         uint8_t Opcode;
00265 
00266         unsigned Service_Action : 5;
00267         unsigned Misc : 3;
00268 
00269         uint8_t LBA_L_M_LB;
00270         uint8_t LBA_L_L_MB;
00271         uint8_t LBA_L_L_LB;
00272 
00273         uint8_t ALC_M_LB;
00274         uint8_t ALC_L_MB;
00275         uint8_t ALC_L_LB;
00276         uint8_t Control;
00277 } __attribute__((packed));
00278 
00279 typedef CDB12 CDB12_t;
00280 
00281 struct CDB_LBA32_16 {
00282         uint8_t Opcode;
00283 
00284         unsigned Service_Action : 5;
00285         unsigned Misc : 3;
00286 
00287         uint8_t LBA_L_M_MB;
00288         uint8_t LBA_L_M_LB;
00289         uint8_t LBA_L_L_MB;
00290         uint8_t LBA_L_L_LB;
00291 
00292         uint8_t A_M_M_MB;
00293         uint8_t A_M_M_LB;
00294         uint8_t A_M_L_MB;
00295         uint8_t A_M_L_LB;
00296 
00297         uint8_t ALC_M_MB;
00298         uint8_t ALC_M_LB;
00299         uint8_t ALC_L_MB;
00300         uint8_t ALC_L_LB;
00301 
00302         uint8_t Misc2;
00303         uint8_t Control;
00304 } __attribute__((packed));
00305 
00306 struct CDB_LBA64_16 {
00307         uint8_t Opcode;
00308         uint8_t Misc;
00309 
00310         uint8_t LBA_M_M_MB;
00311         uint8_t LBA_M_M_LB;
00312         uint8_t LBA_M_L_MB;
00313         uint8_t LBA_M_L_LB;
00314 
00315         uint8_t LBA_L_M_MB;
00316         uint8_t LBA_L_M_LB;
00317         uint8_t LBA_L_L_MB;
00318         uint8_t LBA_L_L_LB;
00319 
00320         uint8_t ALC_M_MB;
00321         uint8_t ALC_M_LB;
00322         uint8_t ALC_L_MB;
00323         uint8_t ALC_L_LB;
00324 
00325         uint8_t Misc2;
00326         uint8_t Control;
00327 } __attribute__((packed));
00328 
00329 struct InquiryResponse {
00330         uint8_t DeviceType : 5;
00331         uint8_t PeripheralQualifier : 3;
00332 
00333         unsigned Reserved : 7;
00334         unsigned Removable : 1;
00335 
00336         uint8_t Version;
00337 
00338         unsigned ResponseDataFormat : 4;
00339         unsigned HISUP : 1;
00340         unsigned NormACA : 1;
00341         unsigned TrmTsk : 1;
00342         unsigned AERC : 1;
00343 
00344         uint8_t AdditionalLength;
00345         //uint8_t Reserved3[2];
00346 
00347         unsigned PROTECT : 1;
00348         unsigned Res : 2;
00349         unsigned ThreePC : 1;
00350         unsigned TPGS : 2;
00351         unsigned ACC : 1;
00352         unsigned SCCS : 1;
00353 
00354         unsigned ADDR16 : 1;
00355         unsigned R1 : 1;
00356         unsigned R2 : 1;
00357         unsigned MCHNGR : 1;
00358         unsigned MULTIP : 1;
00359         unsigned VS : 1;
00360         unsigned ENCSERV : 1;
00361         unsigned BQUE : 1;
00362 
00363         unsigned SoftReset : 1;
00364         unsigned CmdQue : 1;
00365         unsigned Reserved4 : 1;
00366         unsigned Linked : 1;
00367         unsigned Sync : 1;
00368         unsigned WideBus16Bit : 1;
00369         unsigned WideBus32Bit : 1;
00370         unsigned RelAddr : 1;
00371 
00372         uint8_t VendorID[8];
00373         uint8_t ProductID[16];
00374         uint8_t RevisionID[4];
00375 } __attribute__((packed));
00376 
00377 struct CommandBlockWrapperBase {
00378         uint32_t dCBWSignature;
00379         uint32_t dCBWTag;
00380         uint32_t dCBWDataTransferLength;
00381         uint8_t bmCBWFlags;
00382 public:
00383 
00384         CommandBlockWrapperBase() {
00385         }
00386 
00387         CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) :
00388         dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) {
00389         }
00390 } __attribute__((packed));
00391 
00392 struct CommandBlockWrapper : public CommandBlockWrapperBase {
00393 
00394         struct {
00395                 uint8_t bmCBWLUN : 4;
00396                 uint8_t bmReserved1 : 4;
00397         };
00398 
00399         struct {
00400                 uint8_t bmCBWCBLength : 4;
00401                 uint8_t bmReserved2 : 4;
00402         };
00403 
00404         uint8_t CBWCB[16];
00405 
00406 public:
00407         // All zeroed.
00408 
00409         CommandBlockWrapper() :
00410         CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) {
00411                 for(int i = 0; i < 16; i++) CBWCB[i] = 0;
00412         }
00413 
00414         // Generic Wrap, CDB zeroed.
00415 
00416         CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) :
00417         CommandBlockWrapperBase(tag, xflen, flgs),
00418         bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) {
00419                 for(int i = 0; i < 16; i++) CBWCB[i] = 0;
00420                 // Type punning can cause optimization problems and bugs.
00421                 // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this.
00422                 //(((BASICCDB_t *) CBWCB)->LUN) = cmd;
00423                 BASICCDB_t *x = reinterpret_cast<BASICCDB_t *>(CBWCB);
00424                 x->LUN = cmd;
00425         }
00426 
00427         // Wrap for CDB of 6
00428 
00429         CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) :
00430         CommandBlockWrapperBase(tag, xflen, dir),
00431         bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) {
00432                 memcpy(&CBWCB, cdb, 6);
00433         }
00434         // Wrap for CDB of 10
00435 
00436         CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB10_t *cdb, uint8_t dir) :
00437         CommandBlockWrapperBase(tag, xflen, dir),
00438         bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) {
00439                 memcpy(&CBWCB, cdb, 10);
00440         }
00441 } __attribute__((packed));
00442 
00443 struct CommandStatusWrapper {
00444         uint32_t dCSWSignature;
00445         uint32_t dCSWTag;
00446         uint32_t dCSWDataResidue;
00447         uint8_t bCSWStatus;
00448 } __attribute__((packed));
00449 
00450 struct RequestSenseResponce {
00451         uint8_t bResponseCode;
00452         uint8_t bSegmentNumber;
00453 
00454         uint8_t bmSenseKey : 4;
00455         uint8_t bmReserved : 1;
00456         uint8_t bmILI : 1;
00457         uint8_t bmEOM : 1;
00458         uint8_t bmFileMark : 1;
00459 
00460         uint8_t Information[4];
00461         uint8_t bAdditionalLength;
00462         uint8_t CmdSpecificInformation[4];
00463         uint8_t bAdditionalSenseCode;
00464         uint8_t bAdditionalSenseQualifier;
00465         uint8_t bFieldReplaceableUnitCode;
00466         uint8_t SenseKeySpecific[3];
00467 } __attribute__((packed));
00468 
00469 class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter {
00470 protected:
00471         static const uint8_t epDataInIndex; // DataIn endpoint index
00472         static const uint8_t epDataOutIndex; // DataOUT endpoint index
00473         static const uint8_t epInterruptInIndex; // InterruptIN  endpoint index
00474 
00475         Usb *pUsb;
00476         uint8_t bAddress;
00477         uint8_t bConfNum; // configuration number
00478         uint8_t bIface; // interface value
00479         uint8_t bNumEP; // total number of EP in the configuration
00480         uint32_t qNextPollTime; // next poll time
00481         bool bPollEnable; // poll enable flag
00482 
00483         EpInfo epInfo[MASS_MAX_ENDPOINTS];
00484 
00485         uint32_t dCBWTag; // Tag
00486         //uint32_t dCBWDataTransferLength; // Data Transfer Length
00487         uint8_t bLastUsbError; // Last USB error
00488         uint8_t bMaxLUN; // Max LUN
00489         uint8_t bTheLUN; // Active LUN
00490         uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors
00491         uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits
00492         bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes.
00493         bool WriteOk[MASS_MAX_SUPPORTED_LUN];
00494         void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
00495 
00496 
00497         // Additional Initialization Method for Subclasses
00498 
00499         virtual uint8_t OnInit() {
00500                 return 0;
00501         };
00502 public:
00503         BulkOnly(Usb *p);
00504 
00505         uint8_t GetLastUsbError() {
00506                 return bLastUsbError;
00507         };
00508 
00509         uint8_t GetbMaxLUN() {
00510                 return bMaxLUN; // Max LUN
00511         }
00512 
00513         uint8_t GetbTheLUN() {
00514                 return bTheLUN; // Active LUN
00515         }
00516 
00517         bool WriteProtected(uint8_t lun);
00518         uint8_t MediaCTL(uint8_t lun, uint8_t ctl);
00519         uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
00520         uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);
00521         uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
00522         uint8_t LockMedia(uint8_t lun, uint8_t lock);
00523 
00524         bool LUNIsGood(uint8_t lun);
00525         uint32_t GetCapacity(uint8_t lun);
00526         uint16_t GetSectorSize(uint8_t lun);
00527 
00528         // USBDeviceConfig implementation
00529         uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
00530         uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);
00531 
00532         uint8_t Release();
00533         uint8_t Poll();
00534 
00535         virtual uint8_t GetAddress() {
00536                 return bAddress;
00537         };
00538 
00539         // UsbConfigXtracter implementation
00540         void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
00541 
00542         virtual bool DEVCLASSOK(uint8_t klass) {
00543                 return (klass == USB_CLASS_MASS_STORAGE);
00544         }
00545 
00546         uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
00547         uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
00548 
00549 private:
00550         uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
00551         uint8_t TestUnitReady(uint8_t lun);
00552         uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);
00553         uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf);
00554         uint8_t GetMaxLUN(uint8_t *max_lun);
00555         uint8_t SetCurLUN(uint8_t lun);
00556         void Reset();
00557         uint8_t ResetRecovery();
00558         uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf);
00559         void ClearAllEP();
00560         void CheckMedia();
00561         bool CheckLUN(uint8_t lun);
00562         uint8_t Page3F(uint8_t lun);
00563         bool IsValidCBW(uint8_t size, uint8_t *pcbw);
00564         bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);
00565 
00566         bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);
00567 
00568         uint8_t ClearEpHalt(uint8_t index);
00569 #if MS_WANT_PARSER
00570         uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
00571 #endif
00572         uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf);
00573         uint8_t HandleUsbError(uint8_t error, uint8_t index);
00574         uint8_t HandleSCSIError(uint8_t status);
00575 
00576 };
00577 
00578 #endif // __MASSTORAGE_H__