| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
MassStorageClassDevice.c
Go to the documentation of this file.
1 /*
2 * @brief Device mode driver for the library USB Mass Storage Class driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * Copyright(C) Dean Camera, 2011, 2012
7 * All rights reserved.
8 *
9 * @par
10 * Software that is described herein is for illustrative purposes only
11 * which provides customers with programming information regarding the
12 * LPC products. This software is supplied "AS IS" without any warranties of
13 * any kind, and NXP Semiconductors and its licensor disclaim any and
14 * all warranties, express or implied, including all implied warranties of
15 * merchantability, fitness for a particular purpose and non-infringement of
16 * intellectual property rights. NXP Semiconductors assumes no responsibility
17 * or liability for the use of the software, conveys no license or rights under any
18 * patent, copyright, mask work right, or any other intellectual property rights in
19 * or to any products. NXP Semiconductors reserves the right to make changes
20 * in the software without notification. NXP Semiconductors also makes no
21 * representation or warranty that such application will be suitable for the
22 * specified use without further testing or modification.
23 *
24 * @par
25 * Permission to use, copy, modify, and distribute this software and its
26 * documentation is hereby granted, under NXP Semiconductors' and its
27 * licensor's relevant copyrights in the software, without fee, provided that it
28 * is used in conjunction with NXP Semiconductors microcontrollers. This
29 * copyright, permission, and disclaimer notice must appear in all copies of
30 * this code.
31 */
32
33
34 #define __INCLUDE_FROM_USB_DRIVER
35 #include "../../Core/USBMode.h"
36
37 #if defined(USB_CAN_BE_DEVICE)
38
39 #define __INCLUDE_FROM_MS_DRIVER
40 #define __INCLUDE_FROM_MASSSTORAGE_DEVICE_C
41 #include "MassStorageClassDevice.h"
42
43 void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
44 {
45 if (!(Endpoint_IsSETUPReceived(MSInterfaceInfo->Config.PortNumber)))
46 return;
47
48 if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber)
49 return;
50
51 switch (USB_ControlRequest.bRequest)
52 {
53 case MS_REQ_MassStorageReset:
54 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
55 {
56 Endpoint_ClearSETUP(MSInterfaceInfo->Config.PortNumber);
57 Endpoint_ClearStatusStage(MSInterfaceInfo->Config.PortNumber);
58
59 MSInterfaceInfo->State.IsMassStoreReset = true;
60 }
61
62 break;
63 case MS_REQ_GetMaxLUN:
64 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
65 {
66 Endpoint_ClearSETUP(MSInterfaceInfo->Config.PortNumber);
67 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.TotalLUNs - 1);
68 Endpoint_ClearIN(MSInterfaceInfo->Config.PortNumber);
69 Endpoint_ClearStatusStage(MSInterfaceInfo->Config.PortNumber);
70 }
71
72 break;
73 }
74 }
75
76 bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
77 {
78 memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
79
80 for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS(MSInterfaceInfo->Config.PortNumber); EndpointNum++)
81 {
82 uint16_t Size;
83 uint8_t Type;
84 uint8_t Direction;
85 bool DoubleBanked;
86
87 if (EndpointNum == MSInterfaceInfo->Config.DataINEndpointNumber)
88 {
89 Size = MSInterfaceInfo->Config.DataINEndpointSize;
90 Direction = ENDPOINT_DIR_IN;
91 Type = EP_TYPE_BULK;
92 DoubleBanked = MSInterfaceInfo->Config.DataINEndpointDoubleBank;
93 }
94 else if (EndpointNum == MSInterfaceInfo->Config.DataOUTEndpointNumber)
95 {
96 Size = MSInterfaceInfo->Config.DataOUTEndpointSize;
97 Direction = ENDPOINT_DIR_OUT;
98 Type = EP_TYPE_BULK;
99 DoubleBanked = MSInterfaceInfo->Config.DataOUTEndpointDoubleBank;
100 }
101 else
102 {
103 continue;
104 }
105
106 if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->Config.PortNumber, EndpointNum, Type, Direction, Size,
107 DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
108 {
109 return false;
110 }
111 }
112
113 return true;
114 }
115
116 void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
117 {
118 if (USB_DeviceState[MSInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured)
119 return;
120
121 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);
122
123 if (Endpoint_IsReadWriteAllowed(MSInterfaceInfo->Config.PortNumber))
124 {
125 if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
126 {
127 if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
128 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);
129
130 bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo);
131
132 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);// for streaming
133 Endpoint_ClearOUT(MSInterfaceInfo->Config.PortNumber);
134 if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
135 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);
136 MSInterfaceInfo->State.CommandStatus.Status = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail;
137 MSInterfaceInfo->State.CommandStatus.Signature = CPU_TO_LE32(MS_CSW_SIGNATURE);
138 MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag;
139 MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;
140
141 if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue)))
142 Endpoint_StallTransaction(MSInterfaceInfo->Config.PortNumber);
143
144 MS_Device_ReturnCommandStatus(MSInterfaceInfo);
145 }
146 }
147
148 if (MSInterfaceInfo->State.IsMassStoreReset)
149 {
150 Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
151 Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
152
153 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);
154 Endpoint_ClearStall(MSInterfaceInfo->Config.PortNumber);
155 Endpoint_ResetDataToggle(MSInterfaceInfo->Config.PortNumber);
156 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);
157 Endpoint_ClearStall(MSInterfaceInfo->Config.PortNumber);
158 Endpoint_ResetDataToggle(MSInterfaceInfo->Config.PortNumber);
159
160 MSInterfaceInfo->State.IsMassStoreReset = false;
161 }
162 }
163
164 static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
165 {
166 uint16_t BytesProcessed;
167
168 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);
169
170 BytesProcessed = 0;
171 while (Endpoint_Read_Stream_LE(MSInterfaceInfo->Config.PortNumber,
172 &MSInterfaceInfo->State.CommandBlock,
173 (sizeof(MS_CommandBlockWrapper_t) - 16), &BytesProcessed) ==
174 ENDPOINT_RWSTREAM_IncompleteTransfer)
175 {
176 if (MSInterfaceInfo->State.IsMassStoreReset)
177 return false;
178 }
179
180 if ((MSInterfaceInfo->State.CommandBlock.Signature != CPU_TO_LE32(MS_CBW_SIGNATURE)) ||
181 (MSInterfaceInfo->State.CommandBlock.LUN >= MSInterfaceInfo->Config.TotalLUNs) ||
182 (MSInterfaceInfo->State.CommandBlock.Flags & 0x1F) ||
183 (MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0) ||
184 (MSInterfaceInfo->State.CommandBlock.SCSICommandLength > 16))
185 {
186 Endpoint_StallTransaction(MSInterfaceInfo->Config.PortNumber);
187 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);
188 Endpoint_StallTransaction(MSInterfaceInfo->Config.PortNumber);
189
190 return false;
191 }
192
193 BytesProcessed = 0;
194 while (Endpoint_Read_Stream_LE(MSInterfaceInfo->Config.PortNumber,
195 &MSInterfaceInfo->State.CommandBlock.SCSICommandData,
196 MSInterfaceInfo->State.CommandBlock.SCSICommandLength, &BytesProcessed) ==
197 ENDPOINT_RWSTREAM_IncompleteTransfer)
198 {
199 if (MSInterfaceInfo->State.IsMassStoreReset)
200 return false;
201 }
202
203 // Endpoint_ClearOUT();
204
205 return true;
206 }
207
208 static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
209 {
210 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);
211
212 while (Endpoint_IsStalled(MSInterfaceInfo->Config.PortNumber))
213 {
214 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
215 USB_USBTask(MSInterfaceInfo->Config.PortNumber,USB_MODE_Device);
216 #endif
217
218 if (MSInterfaceInfo->State.IsMassStoreReset)
219 return;
220 }
221
222 Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);
223
224 while (Endpoint_IsStalled(MSInterfaceInfo->Config.PortNumber))
225 {
226 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
227 USB_USBTask(MSInterfaceInfo->Config.PortNumber,USB_MODE_Device);
228 #endif
229
230 if (MSInterfaceInfo->State.IsMassStoreReset)
231 return;
232 }
233
234 uint16_t BytesProcessed = 0;
235 while (Endpoint_Write_Stream_LE(MSInterfaceInfo->Config.PortNumber, &MSInterfaceInfo->State.CommandStatus,
236 sizeof(MS_CommandStatusWrapper_t), &BytesProcessed) ==
237 ENDPOINT_RWSTREAM_IncompleteTransfer)
238 {
239 if (MSInterfaceInfo->State.IsMassStoreReset)
240 return;
241 }
242
243 Endpoint_ClearIN(MSInterfaceInfo->Config.PortNumber);
244 }
245
246 #endif