Statistics
| Branch: | Tag: | Revision:

root / LUFA / Drivers / USB / Class / Device / MassStorage.c @ 978b99e5

History | View | Annotate | Download (7.56 KB)

1
/*
2
             LUFA Library
3
     Copyright (C) Dean Camera, 2011.
4

5
  dean [at] fourwalledcubicle [dot] com
6
           www.lufa-lib.org
7
*/
8

    
9
/*
10
  Copyright 2011  Dean Camera (dean [at] fourwalledcubicle [dot] com)
11

12
  Permission to use, copy, modify, distribute, and sell this
13
  software and its documentation for any purpose is hereby granted
14
  without fee, provided that the above copyright notice appear in
15
  all copies and that both that the copyright notice and this
16
  permission notice and warranty disclaimer appear in supporting
17
  documentation, and that the name of the author not be used in
18
  advertising or publicity pertaining to distribution of the
19
  software without specific, written prior permission.
20

21
  The author disclaim all warranties with regard to this
22
  software, including all implied warranties of merchantability
23
  and fitness.  In no event shall the author be liable for any
24
  special, indirect or consequential damages or any damages
25
  whatsoever resulting from loss of use, data or profits, whether
26
  in an action of contract, negligence or other tortious action,
27
  arising out of or in connection with the use or performance of
28
  this software.
29
*/
30

    
31
#define  __INCLUDE_FROM_USB_DRIVER
32
#include "../../Core/USBMode.h"
33

    
34
#if defined(USB_CAN_BE_DEVICE)
35

    
36
#define  __INCLUDE_FROM_MS_DRIVER
37
#define  __INCLUDE_FROM_MASSSTORAGE_DEVICE_C
38
#include "MassStorage.h"
39

    
40
void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
41
{
42
        if (!(Endpoint_IsSETUPReceived()))
43
          return;
44

    
45
        if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber)
46
          return;
47

    
48
        switch (USB_ControlRequest.bRequest)
49
        {
50
                case MS_REQ_MassStorageReset:
51
                        if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
52
                        {
53
                                Endpoint_ClearSETUP();
54
                                Endpoint_ClearStatusStage();
55

    
56
                                MSInterfaceInfo->State.IsMassStoreReset = true;
57
                        }
58

    
59
                        break;
60
                case MS_REQ_GetMaxLUN:
61
                        if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
62
                        {
63
                                Endpoint_ClearSETUP();
64
                                Endpoint_Write_8(MSInterfaceInfo->Config.TotalLUNs - 1);
65
                                Endpoint_ClearIN();
66
                                Endpoint_ClearStatusStage();
67
                        }
68

    
69
                        break;
70
        }
71
}
72

    
73
bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
74
{
75
        memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
76

    
77
        for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++)
78
        {
79
                uint16_t Size;
80
                uint8_t  Type;
81
                uint8_t  Direction;
82
                bool     DoubleBanked;
83

    
84
                if (EndpointNum == MSInterfaceInfo->Config.DataINEndpointNumber)
85
                {
86
                        Size         = MSInterfaceInfo->Config.DataINEndpointSize;
87
                        Direction    = ENDPOINT_DIR_IN;
88
                        Type         = EP_TYPE_BULK;
89
                        DoubleBanked = MSInterfaceInfo->Config.DataINEndpointDoubleBank;
90
                }
91
                else if (EndpointNum == MSInterfaceInfo->Config.DataOUTEndpointNumber)
92
                {
93
                        Size         = MSInterfaceInfo->Config.DataOUTEndpointSize;
94
                        Direction    = ENDPOINT_DIR_OUT;
95
                        Type         = EP_TYPE_BULK;
96
                        DoubleBanked = MSInterfaceInfo->Config.DataOUTEndpointDoubleBank;
97
                }
98
                else
99
                {
100
                        continue;
101
                }
102

    
103
                if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size,
104
                                                 DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
105
                {
106
                        return false;
107
                }
108
        }
109

    
110
        return true;
111
}
112

    
113
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
114
{
115
        if (USB_DeviceState != DEVICE_STATE_Configured)
116
          return;
117

    
118
        Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
119

    
120
        if (Endpoint_IsReadWriteAllowed())
121
        {
122
                if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
123
                {
124
                        if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
125
                          Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
126

    
127
                        bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo);
128

    
129
                        MSInterfaceInfo->State.CommandStatus.Status              = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail;
130
                        MSInterfaceInfo->State.CommandStatus.Signature           = CPU_TO_LE32(MS_CSW_SIGNATURE);
131
                        MSInterfaceInfo->State.CommandStatus.Tag                 = MSInterfaceInfo->State.CommandBlock.Tag;
132
                        MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;
133

    
134
                        if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue)))
135
                          Endpoint_StallTransaction();
136

    
137
                        MS_Device_ReturnCommandStatus(MSInterfaceInfo);
138
                }
139
        }
140

    
141
        if (MSInterfaceInfo->State.IsMassStoreReset)
142
        {
143
                Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
144
                Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
145

    
146
                Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
147
                Endpoint_ClearStall();
148
                Endpoint_ResetDataToggle();
149
                Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
150
                Endpoint_ClearStall();
151
                Endpoint_ResetDataToggle();
152

    
153
                MSInterfaceInfo->State.IsMassStoreReset = false;
154
        }
155
}
156

    
157
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
158
{
159
        uint16_t BytesProcessed;
160

    
161
        Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
162
        
163
        BytesProcessed = 0;
164
        while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock,
165
                                       (sizeof(MS_CommandBlockWrapper_t) - 16), &BytesProcessed) ==
166
                                       ENDPOINT_RWSTREAM_IncompleteTransfer)
167
        {
168
                if (MSInterfaceInfo->State.IsMassStoreReset)
169
                  return false;
170
        }
171

    
172
        if ((MSInterfaceInfo->State.CommandBlock.Signature         != CPU_TO_LE32(MS_CBW_SIGNATURE))     ||
173
            (MSInterfaceInfo->State.CommandBlock.LUN               >= MSInterfaceInfo->Config.TotalLUNs) ||
174
                (MSInterfaceInfo->State.CommandBlock.Flags              & 0x1F)                              ||
175
                (MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0)                                 ||
176
                (MSInterfaceInfo->State.CommandBlock.SCSICommandLength >  16))
177
        {
178
                Endpoint_StallTransaction();
179
                Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
180
                Endpoint_StallTransaction();
181

    
182
                return false;
183
        }
184

    
185
        BytesProcessed = 0;
186
        while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData,
187
                                        MSInterfaceInfo->State.CommandBlock.SCSICommandLength, &BytesProcessed) ==
188
                                        ENDPOINT_RWSTREAM_IncompleteTransfer)
189
        {
190
                if (MSInterfaceInfo->State.IsMassStoreReset)
191
                  return false;
192
        }
193

    
194
        Endpoint_ClearOUT();
195

    
196
        return true;
197
}
198

    
199
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
200
{
201
        Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
202

    
203
        while (Endpoint_IsStalled())
204
        {
205
                #if !defined(INTERRUPT_CONTROL_ENDPOINT)
206
                USB_USBTask();
207
                #endif
208

    
209
                if (MSInterfaceInfo->State.IsMassStoreReset)
210
                  return;
211
        }
212

    
213
        Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
214

    
215
        while (Endpoint_IsStalled())
216
        {
217
                #if !defined(INTERRUPT_CONTROL_ENDPOINT)
218
                USB_USBTask();
219
                #endif
220

    
221
                if (MSInterfaceInfo->State.IsMassStoreReset)
222
                  return;
223
        }
224

    
225
        uint16_t BytesProcessed = 0;
226
        while (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus,
227
                                        sizeof(MS_CommandStatusWrapper_t), &BytesProcessed) ==
228
                                        ENDPOINT_RWSTREAM_IncompleteTransfer)
229
        {
230
                if (MSInterfaceInfo->State.IsMassStoreReset)
231
                  return;
232
        }
233
        
234
        Endpoint_ClearIN();
235
}
236

    
237
#endif