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 #define DEBUG
5 
6 #include <inttypes.h>
7 #include "avrpins.h"
8 #include <avr/pgmspace.h>
9 #include "max3421e.h"
10 #include "usbhost.h"
11 #include "usb_ch9.h"
12 #include "Usb.h"
13 
14 #if defined(ARDUINO) && ARDUINO >=100
15 #include "Arduino.h"
16 #else
17 #include <WProgram.h>
18 #endif
19 
20 #include <confdescparser.h>
21 
22 #define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
23 
24 #define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
25 #define bmREQ_MASSIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
26 
27 // Mass Storage Subclass Constants
28 #define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use
29 #define MASS_SUBCLASS_RBC 0x01
30 #define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI)
31 #define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157
32 #define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB
33 #define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i
34 #define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set
35 #define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI
36 #define MASS_SUBCLASS_IEEE1667 0x08
37 
38 // Mass Storage Class Protocols
39 #define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt)
40 #define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt)
41 #define MASS_PROTO_OBSOLETE 0x02
42 #define MASS_PROTO_BBB 0x50 // Bulk Only Transport
43 #define MASS_PROTO_UAS 0x62
44 
45 // Request Codes
46 #define MASS_REQ_ADSC 0x00
47 #define MASS_REQ_GET 0xFC
48 #define MASS_REQ_PUT 0xFD
49 #define MASS_REQ_GET_MAX_LUN 0xFE
50 #define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset
51 
52 #define MASS_CBW_SIGNATURE 0x43425355
53 #define MASS_CSW_SIGNATURE 0x53425355
54 
55 #define MASS_CMD_DIR_OUT (0 << 7)
56 #define MASS_CMD_DIR_IN (1 << 7)
57 
58 #define SCSI_CMD_INQUIRY 0x12
59 #define SCSI_CMD_REPORT_LUNS 0xA0
60 #define SCSI_CMD_REQUEST_SENSE 0x03
61 #define SCSI_CMD_FORMAT_UNIT 0x04
62 #define SCSI_CMD_READ_6 0x08
63 #define SCSI_CMD_READ_10 0x28
64 #define SCSI_CMD_READ_CAPACITY_10 0x25
65 #define SCSI_CMD_TEST_UNIT_READY 0x00
66 #define SCSI_CMD_WRITE_6 0x0A
67 #define SCSI_CMD_WRITE_10 0x2A
68 #define SCSI_CMD_MODE_SENSE_6 0x1A
69 #define SCSI_CMD_MODE_SENSE_10 0x5A
70 #define SCSI_CMD_START_STOP_UNIT 0x1B
71 
72 #define SCSI_S_NOT_READY 0x02
73 #define SCSI_S_MEDIUM_ERROR 0x03
74 #define SCSI_S_ILLEGAL_REQUEST 0x05
75 #define SCSI_S_UNIT_ATTENTION 0x06
76 
77 #define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
78 #define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
79 
80 
81 #define MASS_ERR_SUCCESS 0x00
82 #define MASS_ERR_PHASE_ERROR 0x02
83 #define MASS_ERR_UNIT_NOT_READY 0x03
84 #define MASS_ERR_UNIT_BUSY 0x04
85 #define MASS_ERR_STALL 0x05
86 #define MASS_ERR_CMD_NOT_SUPPORTED 0x06
87 #define MASS_ERR_INVALID_CSW 0x07
88 #define MASS_ERR_NO_MEDIA 0x08
89 #define MASS_ERR_BAD_LBA 0x09
90 #define MASS_ERR_DEVICE_DISCONNECTED 0x11
91 #define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error
92 #define MASS_ERR_INVALID_LUN 0x13
93 #define MASS_ERR_GENERAL_SCSI_ERROR 0xFE
94 #define MASS_ERR_GENERAL_USB_ERROR 0xFF
95 #define MASS_ERR_USER 0xA0 // For subclasses to define their own error codes
96 
97 #define MASS_TRANS_FLG_CALLBACK 0x01 // Callback is involved
98 #define MASS_TRANS_FLG_NO_STALL_CHECK 0x02 // STALL condition is not checked
99 #define MASS_TRANS_FLG_NO_PHASE_CHECK 0x04 // PHASE_ERROR is not checked
100 
101 struct Capacity {
102  uint8_t data[8];
103  //uint32_t dwBlockAddress;
104  //uint32_t dwBlockLength;
105 } __attribute__((packed));
106 
108  uint8_t DeviceType : 5;
109  uint8_t PeripheralQualifier : 3;
110 
111  unsigned Reserved : 7;
112  unsigned Removable : 1;
113 
114  uint8_t Version;
115 
116  unsigned ResponseDataFormat : 4;
117  unsigned Reserved2 : 1;
118  unsigned NormACA : 1;
119  unsigned TrmTsk : 1;
120  unsigned AERC : 1;
121 
123  uint8_t Reserved3[2];
124 
125  unsigned SoftReset : 1;
126  unsigned CmdQue : 1;
127  unsigned Reserved4 : 1;
128  unsigned Linked : 1;
129  unsigned Sync : 1;
130  unsigned WideBus16Bit : 1;
131  unsigned WideBus32Bit : 1;
132  unsigned RelAddr : 1;
133 
134  uint8_t VendorID[8];
135  uint8_t ProductID[16];
136  uint8_t RevisionID[4];
137 } __attribute__((packed));
138 
140  uint32_t dCBWSignature;
141  uint32_t dCBWTag;
143  uint8_t bmCBWFlags;
144 } __attribute__((packed));
145 
147 
148  struct {
149  uint8_t bmCBWLUN : 4;
150  uint8_t bmReserved1 : 4;
151  };
152 
153  struct {
154  uint8_t bmCBWCBLength : 4;
155  uint8_t bmReserved2 : 4;
156  };
157 
158  uint8_t CBWCB[16];
159 } __attribute__((packed));
160 
162  uint32_t dCSWSignature;
163  uint32_t dCSWTag;
164  uint32_t dCSWDataResidue;
165  uint8_t bCSWStatus;
166 } __attribute__((packed));
167 
169  uint8_t bResponseCode;
170  uint8_t bSegmentNumber;
171 
172  uint8_t bmSenseKey : 4;
173  uint8_t bmReserved : 1;
174  uint8_t bmILI : 1;
175  uint8_t bmEOM : 1;
176  uint8_t bmFileMark : 1;
177 
178  uint8_t Information[4];
184  uint8_t SenseKeySpecific[3];
185 } __attribute__((packed));
186 
187 #define MASS_MAX_ENDPOINTS 3
188 
190 protected:
191  static const uint8_t epDataInIndex; // DataIn endpoint index
192  static const uint8_t epDataOutIndex; // DataOUT endpoint index
193  static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
194 
196  uint8_t bAddress;
197  uint8_t bConfNum; // configuration number
198  uint8_t bIface; // interface value
199  uint8_t bNumEP; // total number of EP in the configuration
200  uint32_t qNextPollTime; // next poll time
201  bool bPollEnable; // poll enable flag
202 
204 
205  uint32_t dCBWTag; // Tag
206  uint32_t dCBWDataTransferLength; // Data Transfer Length
207  uint8_t bLastUsbError; // Last USB error
208  uint8_t bMaxLUN; // Max LUN
209  uint8_t bTheLUN; // Active LUN
210 
211 protected:
213 
214  bool IsValidCBW(uint8_t size, uint8_t *pcbw);
215  bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);
216 
218 
219  uint8_t ClearEpHalt(uint8_t index);
220  uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
221  uint8_t HandleUsbError(uint8_t error, uint8_t index);
222  uint8_t HandleSCSIError(uint8_t status);
223 
224 public:
225  BulkOnly(USB *p);
226 
227  uint8_t GetLastUsbError() {
228  return bLastUsbError;
229  };
230 
231  uint8_t GetbMaxLUN() {
232  return bMaxLUN; // Max LUN
233  }
234 
235  uint8_t GetbTheLUN() {
236  return bTheLUN; // Active LUN
237  }
238 
239  uint8_t Reset();
240  uint8_t GetMaxLUN(uint8_t *max_lun);
241  uint8_t SetCurLUN(uint8_t lun);
242 
243  uint8_t ResetRecovery();
244  uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
245  uint8_t TestUnitReady(uint8_t lun);
246  uint8_t ReadCapacity(uint8_t lun, uint16_t size, uint8_t *buf);
247  uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);
248  uint8_t ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf);
249  uint8_t MediaCTL(uint8_t lun, uint8_t ctl);
250  uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
251  uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);
252  uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
253 
254  // USBDeviceConfig implementation
255  virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
256  virtual uint8_t Release();
257  virtual uint8_t Poll();
258 
259  virtual uint8_t GetAddress() {
260  return bAddress;
261  };
262 
263  // UsbConfigXtracter implementation
264  virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
265 
266 protected:
267  // Additional Initialization Method for Subclasses
268 
269  virtual uint8_t OnInit() {
270  return 0;
271  };
272 };
273 
274 #endif // __MASSTORAGE_H__