USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
masstorage.h
Go to the documentation of this file.
1 #if !defined(__MASSTORAGE_H__)
2 #define __MASSTORAGE_H__
3 
4 
5 //<RANT>
6 // @Oleg -- Perhaps we need a central 'config.h', many of these includes and
7 // defines could be handled there, allowing for easier config.
8 
9 // <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>>
10 // Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives.
11 // Each LUN needs ~13 bytes to be able to track the state of each unit.
12 #define MASS_MAX_SUPPORTED_LUN 8
13 
14 #include <inttypes.h>
15 #include "avrpins.h"
16 #include <avr/pgmspace.h>
17 #include "max3421e.h"
18 #include "usbhost.h"
19 #include "usb_ch9.h"
20 #include "Usb.h"
21 #include <message.h>
22 
23 #if defined(ARDUINO) && ARDUINO >=100
24 #include "Arduino.h"
25 #else
26 #include <WProgram.h>
27 #endif
28 
29 #include <confdescparser.h>
30 
31 // </RANT>
32 
33 
34 #define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
35 
36 #define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
37 #define bmREQ_MASSIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
38 
39 // Mass Storage Subclass Constants
40 #define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use
41 #define MASS_SUBCLASS_RBC 0x01
42 #define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI)
43 #define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157
44 #define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB
45 #define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i
46 #define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set
47 #define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI
48 #define MASS_SUBCLASS_IEEE1667 0x08
49 
50 // Mass Storage Class Protocols
51 #define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt)
52 #define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt)
53 #define MASS_PROTO_OBSOLETE 0x02
54 #define MASS_PROTO_BBB 0x50 // Bulk Only Transport
55 #define MASS_PROTO_UAS 0x62
56 
57 // Request Codes
58 #define MASS_REQ_ADSC 0x00
59 #define MASS_REQ_GET 0xFC
60 #define MASS_REQ_PUT 0xFD
61 #define MASS_REQ_GET_MAX_LUN 0xFE
62 #define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset
63 
64 #define MASS_CBW_SIGNATURE 0x43425355
65 #define MASS_CSW_SIGNATURE 0x53425355
66 
67 #define MASS_CMD_DIR_OUT (0 << 7)
68 #define MASS_CMD_DIR_IN (1 << 7)
69 
70 #define SCSI_CMD_INQUIRY 0x12
71 #define SCSI_CMD_REPORT_LUNS 0xA0
72 #define SCSI_CMD_REQUEST_SENSE 0x03
73 #define SCSI_CMD_FORMAT_UNIT 0x04
74 #define SCSI_CMD_READ_6 0x08
75 #define SCSI_CMD_READ_10 0x28
76 #define SCSI_CMD_READ_CAPACITY_10 0x25
77 #define SCSI_CMD_TEST_UNIT_READY 0x00
78 #define SCSI_CMD_WRITE_6 0x0A
79 #define SCSI_CMD_WRITE_10 0x2A
80 #define SCSI_CMD_MODE_SENSE_6 0x1A
81 #define SCSI_CMD_MODE_SENSE_10 0x5A
82 #define SCSI_CMD_START_STOP_UNIT 0x1B
83 #define SCSI_CMD_PREVENT_REMOVAL 0x1E
84 #define SCSI_S_NOT_READY 0x02
85 #define SCSI_S_MEDIUM_ERROR 0x03
86 #define SCSI_S_ILLEGAL_REQUEST 0x05
87 #define SCSI_S_UNIT_ATTENTION 0x06
88 
89 #define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
90 #define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
91 #define SCSI_ASC_MEDIA_CHANGED 0x28
92 
93 #define MASS_ERR_SUCCESS 0x00
94 #define MASS_ERR_PHASE_ERROR 0x02
95 #define MASS_ERR_UNIT_NOT_READY 0x03
96 #define MASS_ERR_UNIT_BUSY 0x04
97 #define MASS_ERR_STALL 0x05
98 #define MASS_ERR_CMD_NOT_SUPPORTED 0x06
99 #define MASS_ERR_INVALID_CSW 0x07
100 #define MASS_ERR_NO_MEDIA 0x08
101 #define MASS_ERR_BAD_LBA 0x09
102 #define MASS_ERR_MEDIA_CHANGED 0x0A
103 #define MASS_ERR_DEVICE_DISCONNECTED 0x11
104 #define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error
105 #define MASS_ERR_INVALID_LUN 0x13
106 #define MASS_ERR_WRITE_STALL 0x14
107 #define MASS_ERR_READ_NAKS 0x15
108 #define MASS_ERR_WRITE_NAKS 0x16
109 #define MASS_ERR_WRITE_PROTECTED 0x17
110 #define MASS_ERR_GENERAL_SCSI_ERROR 0xFE
111 #define MASS_ERR_GENERAL_USB_ERROR 0xFF
112 #define MASS_ERR_USER 0xA0 // For subclasses to define their own error codes
113 
114 #define MASS_TRANS_FLG_CALLBACK 0x01 // Callback is involved
115 #define MASS_TRANS_FLG_NO_STALL_CHECK 0x02 // STALL condition is not checked
116 #define MASS_TRANS_FLG_NO_PHASE_CHECK 0x04 // PHASE_ERROR is not checked
117 
118 #define MASS_MAX_ENDPOINTS 3
119 
120 struct Capacity {
121  uint8_t data[8];
122  //uint32_t dwBlockAddress;
123  //uint32_t dwBlockLength;
124 } __attribute__((packed));
125 
127  uint8_t DeviceType : 5;
128  uint8_t PeripheralQualifier : 3;
129 
130  unsigned Reserved : 7;
131  unsigned Removable : 1;
132 
133  uint8_t Version;
134 
135  unsigned ResponseDataFormat : 4;
136  unsigned Reserved2 : 1;
137  unsigned NormACA : 1;
138  unsigned TrmTsk : 1;
139  unsigned AERC : 1;
140 
142  uint8_t Reserved3[2];
143 
144  unsigned SoftReset : 1;
145  unsigned CmdQue : 1;
146  unsigned Reserved4 : 1;
147  unsigned Linked : 1;
148  unsigned Sync : 1;
149  unsigned WideBus16Bit : 1;
150  unsigned WideBus32Bit : 1;
151  unsigned RelAddr : 1;
152 
153  uint8_t VendorID[8];
154  uint8_t ProductID[16];
155  uint8_t RevisionID[4];
156 } __attribute__((packed));
157 
159  uint32_t dCBWSignature;
160  uint32_t dCBWTag;
162  uint8_t bmCBWFlags;
163 } __attribute__((packed));
164 
166 
167  struct {
168  uint8_t bmCBWLUN : 4;
169  uint8_t bmReserved1 : 4;
170  };
171 
172  struct {
173  uint8_t bmCBWCBLength : 4;
174  uint8_t bmReserved2 : 4;
175  };
176 
177  uint8_t CBWCB[16];
178 } __attribute__((packed));
179 
181  uint32_t dCSWSignature;
182  uint32_t dCSWTag;
183  uint32_t dCSWDataResidue;
184  uint8_t bCSWStatus;
185 } __attribute__((packed));
186 
188  uint8_t bResponseCode;
189  uint8_t bSegmentNumber;
190 
191  uint8_t bmSenseKey : 4;
192  uint8_t bmReserved : 1;
193  uint8_t bmILI : 1;
194  uint8_t bmEOM : 1;
195  uint8_t bmFileMark : 1;
196 
197  uint8_t Information[4];
203  uint8_t SenseKeySpecific[3];
204 } __attribute__((packed));
205 
207 protected:
208  static const uint8_t epDataInIndex; // DataIn endpoint index
209  static const uint8_t epDataOutIndex; // DataOUT endpoint index
210  static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
211 
213  uint8_t bAddress;
214  uint8_t bConfNum; // configuration number
215  uint8_t bIface; // interface value
216  uint8_t bNumEP; // total number of EP in the configuration
217  uint32_t qNextPollTime; // next poll time
218  bool bPollEnable; // poll enable flag
219 
221 
222  uint32_t dCBWTag; // Tag
223  uint32_t dCBWDataTransferLength; // Data Transfer Length
224  uint8_t bLastUsbError; // Last USB error
225  uint8_t bMaxLUN; // Max LUN
226  uint8_t bTheLUN; // Active LUN
227  uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors
228  uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits
229  bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes.
232 
233 
234  // Additional Initialization Method for Subclasses
235 
236  virtual uint8_t OnInit() {
237  return 0;
238  };
239 public:
240  BulkOnly(USB *p);
241 
242  uint8_t GetLastUsbError() {
243  return bLastUsbError;
244  };
245 
246  uint8_t GetbMaxLUN() {
247  return bMaxLUN; // Max LUN
248  }
249 
250  uint8_t GetbTheLUN() {
251  return bTheLUN; // Active LUN
252  }
253 
254  boolean WriteProtected(uint8_t lun);
255  uint8_t MediaCTL(uint8_t lun, uint8_t ctl);
256  uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
257  uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);
258  uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
259  uint8_t LockMedia(uint8_t lun, uint8_t lock);
260 
261  bool LUNIsGood(uint8_t lun);
262  uint32_t GetCapacity(uint8_t lun);
263  uint16_t GetSectorSize(uint8_t lun);
264 
265  // USBDeviceConfig implementation
266  virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
267  virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);
268 
269  virtual uint8_t Release();
270  virtual uint8_t Poll();
271 
272  virtual uint8_t GetAddress() {
273  return bAddress;
274  };
275 
276  // UsbConfigXtracter implementation
277  virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
278  virtual boolean DEVCLASSOK(uint8_t klass) { return (klass == USB_CLASS_MASS_STORAGE); }
279 
280 
281 private:
282  uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
283  uint8_t TestUnitReady(uint8_t lun);
284  uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);
285  uint8_t ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf);
286  uint8_t GetMaxLUN(uint8_t *max_lun);
287  uint8_t SetCurLUN(uint8_t lun);
288  void Reset();
289  uint8_t ResetRecovery();
290  uint8_t ReadCapacity(uint8_t lun, uint16_t size, uint8_t *buf);
291  void ClearAllEP();
292  void CheckMedia();
293  boolean CheckLUN(uint8_t lun);
294  uint8_t Page3F(uint8_t lun);
295  bool IsValidCBW(uint8_t size, uint8_t *pcbw);
296  bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);
297 
298  bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);
299 
300  uint8_t ClearEpHalt(uint8_t index);
301  uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
302  uint8_t HandleUsbError(uint8_t error, uint8_t index);
303  uint8_t HandleSCSIError(uint8_t status);
304 
305 };
306 
307 #endif // __MASSTORAGE_H__