Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | /********************************************************************* |
2 | File Information: |
||
3 | FileName: usb_function_msd.c |
||
4 | Dependencies: See INCLUDES section below |
||
5 | Processor: PIC18, PIC24, or PIC32 |
||
6 | Compiler: C18, C30, or C32 |
||
7 | Company: Microchip Technology, Inc. |
||
8 | |||
9 | Software License Agreement |
||
10 | |||
11 | The software supplied herewith by Microchip Technology Incorporated |
||
12 | (the Company) for its PICmicro® Microcontroller is intended and |
||
13 | supplied to you, the Companys customer, for use solely and |
||
14 | exclusively on Microchip PICmicro Microcontroller products. The |
||
15 | software is owned by the Company and/or its supplier, and is |
||
16 | protected under applicable copyright laws. All rights are reserved. |
||
17 | Any use in violation of the foregoing restrictions may subject the |
||
18 | user to criminal sanctions under applicable laws, as well as to |
||
19 | civil liability for the breach of the terms and conditions of this |
||
20 | license. |
||
21 | |||
22 | THIS SOFTWARE IS PROVIDED IN AN AS IS CONDITION. NO WARRANTIES, |
||
23 | WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED |
||
24 | TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||
25 | PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, |
||
26 | IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR |
||
27 | CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. |
||
28 | |||
29 | Summary: |
||
30 | This file contains functions, macros, definitions, variables, |
||
31 | datatypes, etc. that are required for use of the MSD function |
||
32 | driver. This file should be included in projects that use the MSD |
||
33 | \function driver. |
||
34 | |||
35 | |||
36 | |||
37 | This file is located in the "\<Install Directory\>\\Microchip\\USB\\MSD |
||
38 | Device Driver" directory. |
||
39 | |||
40 | Description: |
||
41 | USB MSD Function Driver File |
||
42 | |||
43 | This file contains functions, macros, definitions, variables, |
||
44 | datatypes, etc. that are required for use of the MSD function |
||
45 | driver. This file should be included in projects that use the MSD |
||
46 | \function driver. |
||
47 | |||
48 | This file is located in the "\<Install Directory\>\\Microchip\\USB\\MSD |
||
49 | Device Driver" directory. |
||
50 | |||
51 | When including this file in a new project, this file can either be |
||
52 | referenced from the directory in which it was installed or copied |
||
53 | directly into the user application folder. If the first method is |
||
54 | chosen to keep the file located in the folder in which it is installed |
||
55 | then include paths need to be added so that the library and the |
||
56 | application both know where to reference each others files. If the |
||
57 | application folder is located in the same folder as the Microchip |
||
58 | folder (like the current demo folders), then the following include |
||
59 | paths need to be added to the application's project: |
||
60 | |||
61 | ..\\..\\Microchip\\Include |
||
62 | . |
||
63 | |||
64 | If a different directory structure is used, modify the paths as |
||
65 | required. An example using absolute paths instead of relative paths |
||
66 | would be the following: |
||
67 | |||
68 | C:\\Microchip Solutions\\Microchip\\Include |
||
69 | |||
70 | C:\\Microchip Solutions\\My Demo Application |
||
71 | |||
72 | Change History: |
||
73 | Rev Description |
||
74 | ---------- ---------------------------------------------------------- |
||
75 | 2.6 - 2.7a No change |
||
76 | |||
77 | ********************************************************************/ |
||
78 | |||
79 | /** I N C L U D E S **************************************************/ |
||
80 | #include "USB/USB.h" |
||
81 | #include "HardwareProfile.h" |
||
82 | #include "FSConfig.h" |
||
83 | |||
84 | #include "./USB/usb_function_msd.h" |
||
85 | |||
86 | #ifdef USB_USE_MSD |
||
87 | |||
88 | #if MAX_LUN == 0 |
||
89 | #define LUN_INDEX 0 |
||
90 | #else |
||
91 | #define LUN_INDEX gblCBW.bCBWLUN |
||
92 | #endif |
||
93 | |||
94 | #if defined(__C30__) || defined(__C32__) |
||
95 | #if defined(USE_INTERNAL_FLASH) |
||
96 | #include "MDD File System\Internal Flash.h" |
||
97 | #endif |
||
98 | |||
99 | #if defined(USE_SD_INTERFACE_WITH_SPI) |
||
100 | #include "MDD File System\SD-SPI.h" |
||
101 | #endif |
||
102 | |||
103 | extern LUN_FUNCTIONS LUN[MAX_LUN + 1]; |
||
104 | #define LUNMediaInitialize() LUN[LUN_INDEX].MediaInitialize() |
||
105 | #define LUNReadCapacity() LUN[LUN_INDEX].ReadCapacity() |
||
106 | #define LUNReadSectorSize() LUN[LUN_INDEX].ReadSectorSize() |
||
107 | #define LUNMediaDetect() LUN[LUN_INDEX].MediaDetect() |
||
108 | #define LUNSectorWrite(bLBA,pDest,Write0) LUN[LUN_INDEX].SectorWrite(bLBA, pDest, Write0) |
||
109 | #define LUNWriteProtectState() LUN[LUN_INDEX].WriteProtectState() |
||
110 | #define LUNSectorRead(bLBA,pSrc) LUN[LUN_INDEX].SectorRead(bLBA, pSrc) |
||
111 | #else |
||
112 | #if defined(USE_INTERNAL_FLASH) |
||
113 | #include "MDD File System\Internal Flash.h" |
||
114 | #endif |
||
115 | |||
116 | #if defined(USE_SD_INTERFACE_WITH_SPI) |
||
117 | #include "MDD File System\SD-SPI.h" |
||
118 | #endif |
||
119 | |||
120 | #define LUNMediaInitialize() MDD_MediaInitialize() |
||
121 | #define LUNReadCapacity() MDD_ReadCapacity() |
||
122 | #define LUNReadSectorSize() MDD_ReadSectorSize() |
||
123 | #define LUNMediaDetect() MDD_MediaDetect() |
||
124 | #define LUNSectorWrite(bLBA,pDest,Write0) MDD_SectorWrite(bLBA, pDest, Write0) |
||
125 | #define LUNWriteProtectState() MDD_WriteProtectState() |
||
126 | #define LUNSectorRead(bLBA,pSrc) MDD_SectorRead(bLBA, pSrc) |
||
127 | #endif |
||
128 | |||
129 | /** V A R I A B L E S ************************************************/ |
||
130 | #pragma udata |
||
131 | BYTE MSD_State; // Takes values MSD_WAIT, MSD_DATA_IN or MSD_DATA_OUT |
||
132 | USB_MSD_CBW gblCBW; |
||
133 | BYTE gblCBWLength; |
||
134 | RequestSenseResponse gblSenseData[MAX_LUN + 1]; |
||
135 | BYTE *ptrNextData; |
||
136 | USB_HANDLE USBMSDOutHandle; |
||
137 | USB_HANDLE USBMSDInHandle; |
||
138 | WORD MSBBufferIndex; |
||
139 | WORD gblMediaPresent; |
||
140 | BOOL SoftDetach[MAX_LUN + 1]; |
||
141 | static BYTE MSDCommandState = MSD_COMMAND_WAIT; |
||
142 | |||
143 | static WORD_VAL TransferLength; |
||
144 | static DWORD_VAL LBA; |
||
145 | |||
146 | /* |
||
147 | * Number of Blocks and Block Length are global because |
||
148 | * for every READ_10 and WRITE_10 command need to verify if the last LBA |
||
149 | * is less than gblNumBLKS |
||
150 | */ |
||
151 | DWORD_VAL gblNumBLKS,gblBLKLen; |
||
152 | extern const ROM InquiryResponse inq_resp; |
||
153 | |||
154 | /** P R I V A T E P R O T O T Y P E S ***************************************/ |
||
155 | BYTE MSDProcessCommand(void); |
||
156 | BYTE MSDReadHandler(void); |
||
157 | BYTE MSDWriteHandler(void); |
||
158 | void ResetSenseData(void); |
||
159 | |||
160 | /** D E C L A R A T I O N S **************************************************/ |
||
161 | #pragma code |
||
162 | |||
163 | /** C L A S S S P E C I F I C R E Q ****************************************/ |
||
164 | |||
165 | /****************************************************************************** |
||
166 | Function: |
||
167 | void USBMSDInit(void) |
||
168 | |||
169 | Summary: |
||
170 | This routine initializes the MSD class packet handles, prepares to |
||
171 | receive a MSD packet, and initializes the MSD state machine. This |
||
172 | \function should be called once after the device is enumerated. |
||
173 | |||
174 | Description: |
||
175 | This routine initializes the MSD class packet handles, prepares to |
||
176 | receive a MSD packet, and initializes the MSD state machine. This |
||
177 | \function should be called once after the device is enumerated. |
||
178 | |||
179 | Typical Usage: |
||
180 | <code> |
||
181 | void USBCBInitEP(void) |
||
182 | { |
||
183 | USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); |
||
184 | USBMSDInit(); |
||
185 | } |
||
186 | </code> |
||
187 | Conditions: |
||
188 | The device should already be enumerated with a configuration that |
||
189 | supports MSD before calling this function. |
||
190 | |||
191 | Paramters: None |
||
192 | |||
193 | Remarks: |
||
194 | None |
||
195 | ****************************************************************************/ |
||
196 | void USBMSDInit(void) |
||
197 | { |
||
198 | USBMSDInHandle = 0; |
||
199 | USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP,(BYTE*)&msd_cbw,MSD_OUT_EP_SIZE); |
||
200 | MSD_State=MSD_WAIT; |
||
201 | gblNumBLKS.Val = 0; |
||
202 | gblBLKLen.Val = 0; |
||
203 | |||
204 | gblMediaPresent = 0; |
||
205 | |||
206 | //For each of the possible logical units |
||
207 | for(gblCBW.bCBWLUN=0;gblCBW.bCBWLUN<(MAX_LUN + 1);gblCBW.bCBWLUN++) |
||
208 | { |
||
209 | //clear all of the soft detach variables |
||
210 | SoftDetach[gblCBW.bCBWLUN] = FALSE; |
||
211 | |||
212 | //see if the media is attached |
||
213 | if(LUNMediaDetect()) |
||
214 | { |
||
215 | //initialize the media |
||
216 | if(LUNMediaInitialize()) |
||
217 | { |
||
218 | //if the media was present and successfully initialized |
||
219 | // then mark and indicator that the media is ready |
||
220 | gblMediaPresent |= (1<<gblCBW.bCBWLUN); |
||
221 | } |
||
222 | } |
||
223 | ResetSenseData(); |
||
224 | } |
||
225 | } |
||
226 | |||
227 | /****************************************************************************** |
||
228 | Function: |
||
229 | void USBCheckMSDRequest(void) |
||
230 | |||
231 | Summary: |
||
232 | This routine handles MSD specific request that happen on EP0. |
||
233 | This function should be called from the USBCBCheckOtherReq() call back |
||
234 | function whenever implementing an MSD device. |
||
235 | |||
236 | Description: |
||
237 | This routine handles MSD specific request that happen on EP0. These |
||
238 | include, but are not limited to, the standard RESET and GET_MAX_LUN |
||
239 | command requests. This function should be called from the |
||
240 | USBCBCheckOtherReq() call back function whenever using an MSD device. |
||
241 | |||
242 | Typical Usage: |
||
243 | <code> |
||
244 | void USBCBCheckOtherReq(void) |
||
245 | { |
||
246 | //Since the stack didn't handle the request I need to check |
||
247 | // my class drivers to see if it is for them |
||
248 | USBCheckMSDRequest(); |
||
249 | } |
||
250 | </code> |
||
251 | |||
252 | PreCondition: |
||
253 | None |
||
254 | |||
255 | Parameters: |
||
256 | None |
||
257 | |||
258 | Return Values: |
||
259 | None |
||
260 | |||
261 | Remarks: |
||
262 | None |
||
263 | |||
264 | *****************************************************************************/ |
||
265 | void USBCheckMSDRequest(void) |
||
266 | { |
||
267 | if(SetupPkt.Recipient != USB_SETUP_RECIPIENT_INTERFACE_BITFIELD) return; |
||
268 | if(SetupPkt.bIntfID != MSD_INTF_ID) return; |
||
269 | |||
270 | switch(SetupPkt.bRequest) |
||
271 | { |
||
272 | case MSD_RESET: |
||
273 | break; |
||
274 | case GET_MAX_LUN: |
||
275 | //If the host asks for the maximum number of logical units |
||
276 | // then send out a packet with that information |
||
277 | CtrlTrfData[0] = MAX_LUN; |
||
278 | USBEP0SendRAMPtr((BYTE*)&CtrlTrfData[0],1,USB_EP0_INCLUDE_ZERO); |
||
279 | break; |
||
280 | } //end switch(SetupPkt.bRequest) |
||
281 | } |
||
282 | |||
283 | /********************************************************************************* |
||
284 | Function: |
||
285 | BYTE MSDTasks(void) |
||
286 | |||
287 | Summary: |
||
288 | This function runs the MSD class state machines and all of its |
||
289 | sub-systems. This function should be called periodically once the |
||
290 | device is in the configured state in order to keep the MSD state |
||
291 | machine going. |
||
292 | Description: |
||
293 | This function runs the MSD class state machines and all of its |
||
294 | sub-systems. This function should be called periodically once the |
||
295 | device is in the configured state in order to keep the MSD state |
||
296 | machine going. |
||
297 | |||
298 | Typical Usage: |
||
299 | <code> |
||
300 | void main(void) |
||
301 | { |
||
302 | USBDeviceInit(); |
||
303 | while(1) |
||
304 | { |
||
305 | USBDeviceTasks(); |
||
306 | if((USBGetDeviceState() \< CONFIGURED_STATE) || |
||
307 | (USBIsDeviceSuspended() == TRUE)) |
||
308 | { |
||
309 | //Either the device is not configured or we are suspended |
||
310 | // so we don't want to do execute any application code |
||
311 | continue; //go back to the top of the while loop |
||
312 | } |
||
313 | else |
||
314 | { |
||
315 | //Keep the MSD state machine going |
||
316 | MSDTasks(); |
||
317 | |||
318 | //Run application code. |
||
319 | UserApplication(); |
||
320 | } |
||
321 | } |
||
322 | } |
||
323 | </code> |
||
324 | Conditions: |
||
325 | None |
||
326 | Return Values: |
||
327 | BYTE - the current state of the MSD state machine the valid values are |
||
328 | defined in MSD.h under the MSDTasks state machine declaration section. |
||
329 | The possible values are the following\: |
||
330 | * MSD_WAIT |
||
331 | * MSD_DATA_IN |
||
332 | * MSD_DATA_OUT |
||
333 | * MSD_SEND_CSW |
||
334 | Remarks: |
||
335 | None |
||
336 | *********************************************************************************/ |
||
337 | BYTE MSDTasks(void) |
||
338 | { |
||
339 | BYTE i; |
||
340 | |||
341 | switch(MSD_State) |
||
342 | { |
||
343 | case MSD_WAIT: |
||
344 | { |
||
345 | //If the MSD state machine is waiting for something to happen |
||
346 | if(!USBHandleBusy(USBMSDOutHandle)) |
||
347 | { |
||
348 | //If we received an OUT packet from the host |
||
349 | // then copy the data from the buffer to a global |
||
350 | // buffer so that we can keep the information but |
||
351 | // reuse the buffer |
||
352 | gblCBW.dCBWSignature=msd_cbw.dCBWSignature; |
||
353 | gblCBW.dCBWTag=msd_cbw.dCBWTag; |
||
354 | gblCBW.dCBWDataTransferLength=msd_cbw.dCBWDataTransferLength; |
||
355 | gblCBW.bCBWFlags=msd_cbw.bCBWFlags; |
||
356 | gblCBW.bCBWLUN=msd_cbw.bCBWLUN; |
||
357 | gblCBW.bCBWCBLength=msd_cbw.bCBWCBLength; // 3 MSB are zero |
||
358 | |||
359 | for (i=0;i<msd_cbw.bCBWCBLength;i++) |
||
360 | { |
||
361 | gblCBW.CBWCB[i]=msd_cbw.CBWCB[i]; |
||
362 | } |
||
363 | |||
364 | gblCBWLength=USBHandleGetLength(USBMSDOutHandle); |
||
365 | |||
366 | //If this CBW is valid? |
||
367 | if ((gblCBWLength==MSD_CBW_SIZE)&&(gblCBW.dCBWSignature==0x43425355)) |
||
368 | { |
||
369 | //Is this CBW meaningful? |
||
370 | if((gblCBW.bCBWLUN<=0x0f) |
||
371 | &&(gblCBW.bCBWCBLength<=0x10) |
||
372 | &&(gblCBW.bCBWCBLength>=0x01) |
||
373 | &&(gblCBW.bCBWFlags==0x00||gblCBW.bCBWFlags==0x80)) |
||
374 | { |
||
375 | //Prepare the CSW to be sent |
||
376 | msd_csw.dCSWTag=gblCBW.dCBWTag; |
||
377 | msd_csw.dCSWSignature=0x53425355; |
||
378 | |||
379 | /* If direction is device to host*/ |
||
380 | if (gblCBW.bCBWFlags==0x80) |
||
381 | { |
||
382 | MSD_State=MSD_DATA_IN; |
||
383 | } |
||
384 | else if (gblCBW.bCBWFlags==0x00) |
||
385 | { |
||
386 | /* If direction is host to device*/ |
||
387 | /* prepare to read data in msd_buffer */ |
||
388 | MSD_State=MSD_DATA_OUT; |
||
389 | } |
||
390 | } |
||
391 | } |
||
392 | } |
||
393 | break; |
||
394 | } |
||
395 | case MSD_DATA_IN: |
||
396 | if(MSDProcessCommand() == MSD_COMMAND_WAIT) |
||
397 | { |
||
398 | // Done processing the command, send the status |
||
399 | MSD_State = MSD_SEND_CSW; |
||
400 | } |
||
401 | break; |
||
402 | case MSD_DATA_OUT: |
||
403 | if(MSDProcessCommand() == MSD_COMMAND_WAIT) |
||
404 | { |
||
405 | /* Finished receiving the data prepare and send the status */ |
||
406 | if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue!=0)) |
||
407 | { |
||
408 | msd_csw.bCSWStatus=0x02; |
||
409 | } |
||
410 | MSD_State = MSD_SEND_CSW; |
||
411 | } |
||
412 | break; |
||
413 | case MSD_SEND_CSW: |
||
414 | if(USBHandleBusy(USBMSDInHandle)) |
||
415 | { |
||
416 | //The TX buffer is not ready to send the status yet. |
||
417 | break; |
||
418 | } |
||
419 | |||
420 | USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,(BYTE*)&msd_csw,MSD_CSW_SIZE); |
||
421 | |||
422 | //Get ready for next command to come in |
||
423 | if(!USBHandleBusy(USBMSDOutHandle)) |
||
424 | { |
||
425 | USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP,(BYTE*)&msd_cbw,sizeof(msd_cbw)); |
||
426 | } |
||
427 | |||
428 | MSD_State=MSD_WAIT; |
||
429 | break; |
||
430 | } |
||
431 | |||
432 | return MSD_State; |
||
433 | } |
||
434 | |||
435 | /****************************************************************************** |
||
436 | Function: |
||
437 | void MSDProcessCommandMediaPresent(void) |
||
438 | |||
439 | Description: |
||
440 | This funtion processes a command received through the MSD |
||
441 | class driver |
||
442 | |||
443 | PreCondition: |
||
444 | None |
||
445 | |||
446 | Paramters: |
||
447 | None |
||
448 | |||
449 | Return Values: |
||
450 | BYTE - the current state of the MSDProcessCommand state |
||
451 | machine. The valid values are defined in MSD.h under the |
||
452 | MSDProcessCommand state machine declaration section |
||
453 | |||
454 | Remarks: |
||
455 | None |
||
456 | |||
457 | *****************************************************************************/ |
||
458 | void MSDProcessCommandMediaPresent(void) |
||
459 | { |
||
460 | BYTE i; |
||
461 | |||
462 | switch(MSDCommandState) |
||
463 | { |
||
464 | case MSD_COMMAND_WAIT: |
||
465 | //copy the received command to the command state machine |
||
466 | MSDCommandState = gblCBW.CBWCB[0]; |
||
467 | break; |
||
468 | case MSD_INQUIRY: |
||
469 | { |
||
470 | //copy the inquiry results from the defined ROM buffer |
||
471 | // into the USB buffer so that it can be transmitted |
||
472 | memcpypgm2ram( |
||
473 | (void *)&msd_buffer[0], |
||
474 | (ROM void*)&inq_resp, |
||
475 | sizeof(InquiryResponse) |
||
476 | ); |
||
477 | msd_csw.dCSWDataResidue=sizeof(InquiryResponse); |
||
478 | msd_csw.bCSWStatus=0x00; // success |
||
479 | MSDCommandState = MSD_COMMAND_RESPONSE; |
||
480 | break; |
||
481 | } |
||
482 | case MSD_READ_CAPACITY: |
||
483 | { |
||
484 | //If the host asked for the capacity of the device |
||
485 | DWORD_VAL sectorSize; |
||
486 | DWORD_VAL capacity; |
||
487 | |||
488 | msd_csw.bCSWStatus=0x00; // success |
||
489 | |||
490 | //get the information from the physical media |
||
491 | capacity.Val = LUNReadCapacity(); |
||
492 | sectorSize.Val = LUNReadSectorSize(); |
||
493 | |||
494 | //copy the data to the buffer |
||
495 | msd_buffer[0]=capacity.v[3]; |
||
496 | msd_buffer[1]=capacity.v[2]; |
||
497 | msd_buffer[2]=capacity.v[1]; |
||
498 | msd_buffer[3]=capacity.v[0]; |
||
499 | |||
500 | msd_buffer[4]=sectorSize.v[3]; |
||
501 | msd_buffer[5]=sectorSize.v[2]; |
||
502 | msd_buffer[6]=sectorSize.v[1]; |
||
503 | msd_buffer[7]=sectorSize.v[0]; |
||
504 | |||
505 | msd_csw.dCSWDataResidue=0x08; // size of response |
||
506 | MSDCommandState = MSD_COMMAND_RESPONSE; |
||
507 | break; |
||
508 | } |
||
509 | case MSD_READ_10: |
||
510 | if(MSDReadHandler() == MSD_READ10_WAIT) |
||
511 | { |
||
512 | MSDCommandState = MSD_COMMAND_WAIT; |
||
513 | } |
||
514 | break; |
||
515 | case MSD_WRITE_10: |
||
516 | if(MSDWriteHandler() == MSD_WRITE10_WAIT) |
||
517 | { |
||
518 | MSDCommandState = MSD_COMMAND_WAIT; |
||
519 | } |
||
520 | break; |
||
521 | case MSD_REQUEST_SENSE: |
||
522 | for(i=0;i<sizeof(RequestSenseResponse);i++) |
||
523 | { |
||
524 | msd_buffer[i]=gblSenseData[LUN_INDEX]._byte[i]; |
||
525 | } |
||
526 | |||
527 | msd_csw.dCSWDataResidue=sizeof(RequestSenseResponse); |
||
528 | msd_csw.bCSWStatus=0x0; // success |
||
529 | MSDCommandState = MSD_COMMAND_RESPONSE; |
||
530 | break; |
||
531 | case MSD_MODE_SENSE: |
||
532 | msd_buffer[0]=0x02; |
||
533 | msd_buffer[1]=0x00; |
||
534 | msd_buffer[2]=0x00; |
||
535 | msd_buffer[3]=0x00; |
||
536 | |||
537 | msd_csw.bCSWStatus=0x0; |
||
538 | msd_csw.dCSWDataResidue=0x04; |
||
539 | MSDCommandState = MSD_COMMAND_RESPONSE; |
||
540 | break; |
||
541 | case MSD_PREVENT_ALLOW_MEDIUM_REMOVAL: |
||
542 | if(LUNMediaDetect()) |
||
543 | { |
||
544 | msd_csw.bCSWStatus=0x00; |
||
545 | msd_csw.dCSWDataResidue=0x00; |
||
546 | } |
||
547 | else |
||
548 | { |
||
549 | gblSenseData[LUN_INDEX].SenseKey=S_NOT_READY; |
||
550 | gblSenseData[LUN_INDEX].ASC=ASC_MEDIUM_NOT_PRESENT; |
||
551 | gblSenseData[LUN_INDEX].ASCQ=ASCQ_MEDIUM_NOT_PRESENT; |
||
552 | msd_csw.bCSWStatus=0x01; |
||
553 | } |
||
554 | MSDCommandState = MSD_COMMAND_WAIT; |
||
555 | break; |
||
556 | case MSD_TEST_UNIT_READY: |
||
557 | if((gblSenseData[LUN_INDEX].SenseKey==S_UNIT_ATTENTION) && (msd_csw.bCSWStatus==1)) |
||
558 | { |
||
559 | MSDCommandState = MSD_COMMAND_WAIT; |
||
560 | } |
||
561 | else |
||
562 | { |
||
563 | ResetSenseData(); |
||
564 | msd_csw.dCSWDataResidue=0x00; |
||
565 | MSDCommandState = MSD_COMMAND_WAIT; |
||
566 | } |
||
567 | break; |
||
568 | case MSD_VERIFY: |
||
569 | //Fall through to STOP_START |
||
570 | case MSD_STOP_START: |
||
571 | msd_csw.bCSWStatus=0x0; |
||
572 | msd_csw.dCSWDataResidue=0x00; |
||
573 | MSDCommandState = MSD_COMMAND_WAIT; |
||
574 | break; |
||
575 | case MSD_COMMAND_RESPONSE: |
||
576 | if(USBHandleBusy(USBMSDInHandle) == FALSE) |
||
577 | { |
||
578 | USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,(BYTE*)&msd_buffer[0],msd_csw.dCSWDataResidue); |
||
579 | MSDCommandState = MSD_COMMAND_WAIT; |
||
580 | |||
581 | msd_csw.dCSWDataResidue=0; |
||
582 | } |
||
583 | break; |
||
584 | case MSD_COMMAND_ERROR: |
||
585 | default: |
||
586 | ResetSenseData(); |
||
587 | gblSenseData[LUN_INDEX].SenseKey=S_ILLEGAL_REQUEST; |
||
588 | gblSenseData[LUN_INDEX].ASC=ASC_INVALID_COMMAND_OPCODE; |
||
589 | gblSenseData[LUN_INDEX].ASCQ=ASCQ_INVALID_COMMAND_OPCODE; |
||
590 | msd_csw.bCSWStatus=0x01; |
||
591 | msd_csw.dCSWDataResidue=0x00; |
||
592 | MSDCommandState = MSD_COMMAND_RESPONSE; |
||
593 | break; |
||
594 | } // end switch |
||
595 | } |
||
596 | |||
597 | /****************************************************************************** |
||
598 | Function: |
||
599 | void MSDProcessCommandMediaAbsent(void) |
||
600 | |||
601 | Description: |
||
602 | This funtion processes a command received through the MSD |
||
603 | class driver |
||
604 | |||
605 | PreCondition: |
||
606 | None |
||
607 | |||
608 | Parameters: |
||
609 | None |
||
610 | |||
611 | Return Values: |
||
612 | BYTE - the current state of the MSDProcessCommand state |
||
613 | machine. The valid values are defined in MSD.h under the |
||
614 | MSDProcessCommand state machine declaration section |
||
615 | |||
616 | Remarks: |
||
617 | None |
||
618 | |||
619 | *****************************************************************************/ |
||
620 | void MSDProcessCommandMediaAbsent(void) |
||
621 | { |
||
622 | BYTE i; |
||
623 | |||
624 | switch(MSDCommandState) |
||
625 | { |
||
626 | case MSD_REQUEST_SENSE: |
||
627 | { |
||
628 | ResetSenseData(); |
||
629 | gblSenseData[LUN_INDEX].SenseKey=S_NOT_READY; |
||
630 | gblSenseData[LUN_INDEX].ASC=ASC_MEDIUM_NOT_PRESENT; |
||
631 | gblSenseData[LUN_INDEX].ASCQ=ASCQ_MEDIUM_NOT_PRESENT; |
||
632 | |||
633 | for(i=0;i<sizeof(RequestSenseResponse);i++) |
||
634 | { |
||
635 | msd_buffer[i]=gblSenseData[LUN_INDEX]._byte[i]; |
||
636 | } |
||
637 | |||
638 | msd_csw.dCSWDataResidue=sizeof(RequestSenseResponse); |
||
639 | msd_csw.bCSWStatus=0x0; // success |
||
640 | MSDCommandState = MSD_COMMAND_RESPONSE; |
||
641 | break; |
||
642 | } |
||
643 | case MSD_PREVENT_ALLOW_MEDIUM_REMOVAL: |
||
644 | case MSD_TEST_UNIT_READY: |
||
645 | { |
||
646 | msd_csw.bCSWStatus=0x01; |
||
647 | MSDCommandState = MSD_COMMAND_WAIT; |
||
648 | break; |
||
649 | } |
||
650 | case MSD_INQUIRY: |
||
651 | { |
||
652 | memcpypgm2ram( |
||
653 | (void *)&msd_buffer[0], |
||
654 | (ROM void*)&inq_resp, |
||
655 | sizeof(InquiryResponse) |
||
656 | ); |
||
657 | msd_csw.dCSWDataResidue=sizeof(InquiryResponse); |
||
658 | msd_csw.bCSWStatus=0x00; // success |
||
659 | MSDCommandState = MSD_COMMAND_RESPONSE; |
||
660 | break; |
||
661 | } |
||
662 | case MSD_COMMAND_WAIT: |
||
663 | { |
||
664 | MSDCommandState = gblCBW.CBWCB[0]; |
||
665 | break; |
||
666 | } |
||
667 | case MSD_COMMAND_RESPONSE: |
||
668 | if(USBHandleBusy(USBMSDInHandle) == FALSE) |
||
669 | { |
||
670 | USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,(BYTE*)&msd_buffer[0],msd_csw.dCSWDataResidue); |
||
671 | MSDCommandState = MSD_COMMAND_WAIT; |
||
672 | |||
673 | msd_csw.dCSWDataResidue=0; |
||
674 | } |
||
675 | break; |
||
676 | default: |
||
677 | { |
||
678 | //Stall MSD endpoint IN |
||
679 | USBStallEndpoint(MSD_DATA_IN_EP,1); |
||
680 | msd_csw.bCSWStatus=0x01; |
||
681 | MSDCommandState = MSD_COMMAND_WAIT; |
||
682 | break; |
||
683 | } |
||
684 | } |
||
685 | } |
||
686 | |||
687 | /****************************************************************************** |
||
688 | Function: |
||
689 | BYTE MSDProcessCommand(void) |
||
690 | |||
691 | Description: |
||
692 | This funtion processes a command received through the MSD |
||
693 | class driver |
||
694 | |||
695 | PreCondition: |
||
696 | None |
||
697 | |||
698 | Paramters: |
||
699 | None |
||
700 | |||
701 | Return Values: |
||
702 | BYTE - the current state of the MSDProcessCommand state |
||
703 | machine. The valid values are defined in MSD.h under the |
||
704 | MSDProcessCommand state machine declaration section |
||
705 | |||
706 | Remarks: |
||
707 | None |
||
708 | |||
709 | *****************************************************************************/ |
||
710 | BYTE MSDProcessCommand(void) |
||
711 | { |
||
712 | if(LUNMediaDetect() == FALSE || SoftDetach[gblCBW.bCBWLUN] == TRUE) |
||
713 | { |
||
714 | gblMediaPresent &= ~(1<<gblCBW.bCBWLUN); |
||
715 | |||
716 | MSDProcessCommandMediaAbsent(); |
||
717 | } |
||
718 | else |
||
719 | { |
||
720 | if((gblMediaPresent & (1<<gblCBW.bCBWLUN)) == 0) |
||
721 | { |
||
722 | if(LUNMediaInitialize()) |
||
723 | { |
||
724 | gblMediaPresent |= (1<<gblCBW.bCBWLUN); |
||
725 | |||
726 | gblSenseData[LUN_INDEX].SenseKey=S_UNIT_ATTENTION; |
||
727 | gblSenseData[LUN_INDEX].ASC=0x28; |
||
728 | gblSenseData[LUN_INDEX].ASCQ=0x00; |
||
729 | msd_csw.bCSWStatus=0x01; |
||
730 | |||
731 | MSDProcessCommandMediaPresent(); |
||
732 | } |
||
733 | else |
||
734 | { |
||
735 | MSDProcessCommandMediaAbsent(); |
||
736 | } |
||
737 | } |
||
738 | else |
||
739 | { |
||
740 | MSDProcessCommandMediaPresent(); |
||
741 | } |
||
742 | } |
||
743 | |||
744 | return MSDCommandState; |
||
745 | } |
||
746 | |||
747 | /****************************************************************************** |
||
748 | Function: |
||
749 | BYTE MSDReadHandler(void) |
||
750 | |||
751 | Description: |
||
752 | This funtion processes a read command received through |
||
753 | the MSD class driver |
||
754 | |||
755 | PreCondition: |
||
756 | None |
||
757 | |||
758 | Parameters: |
||
759 | None |
||
760 | |||
761 | Return Values: |
||
762 | BYTE - the current state of the MSDReadHandler state |
||
763 | machine. The valid values are defined in MSD.h under the |
||
764 | MSDReadHandler state machine declaration section |
||
765 | |||
766 | Remarks: |
||
767 | None |
||
768 | |||
769 | *****************************************************************************/ |
||
770 | |||
771 | BYTE MSDReadHandler(void) |
||
772 | { |
||
773 | static BYTE MSDReadState = MSD_READ10_WAIT; |
||
774 | |||
775 | switch(MSDReadState) |
||
776 | { |
||
777 | case MSD_READ10_WAIT: |
||
778 | LBA.v[3]=gblCBW.CBWCB[2]; |
||
779 | LBA.v[2]=gblCBW.CBWCB[3]; |
||
780 | LBA.v[1]=gblCBW.CBWCB[4]; |
||
781 | LBA.v[0]=gblCBW.CBWCB[5]; |
||
782 | |||
783 | TransferLength.v[1]=gblCBW.CBWCB[7]; |
||
784 | TransferLength.v[0]=gblCBW.CBWCB[8]; |
||
785 | |||
786 | msd_csw.bCSWStatus=0x0; |
||
787 | msd_csw.dCSWDataResidue=0x0; |
||
788 | |||
789 | MSDReadState = MSD_READ10_BLOCK; |
||
790 | //Fall through to MSD_READ_BLOCK |
||
791 | case MSD_READ10_BLOCK: |
||
792 | if(TransferLength.Val == 0) |
||
793 | { |
||
794 | MSDReadState = MSD_READ10_WAIT; |
||
795 | break; |
||
796 | } |
||
797 | |||
798 | TransferLength.Val--; // we have read 1 LBA |
||
799 | MSDReadState = MSD_READ10_SECTOR; |
||
800 | //Fall through to MSD_READ10_SECTOR |
||
801 | case MSD_READ10_SECTOR: |
||
802 | //if the old data isn't completely sent yet |
||
803 | if(USBHandleBusy(USBMSDInHandle) != 0) |
||
804 | { |
||
805 | break; |
||
806 | } |
||
807 | |||
808 | if(LUNSectorRead(LBA.Val, (BYTE*)&msd_buffer[0]) != TRUE) |
||
809 | { |
||
810 | msd_csw.bCSWStatus=0x01; // Error 0x01 Refer page#18 |
||
811 | // of BOT specifications |
||
812 | /* Don't read any more data*/ |
||
813 | msd_csw.dCSWDataResidue=0x0; |
||
814 | |||
815 | MSD_State = MSD_DATA_IN; |
||
816 | break; |
||
817 | } |
||
818 | |||
819 | LBA.Val++; |
||
820 | |||
821 | msd_csw.bCSWStatus=0x00; // success |
||
822 | msd_csw.dCSWDataResidue=BLOCKLEN_512;//in order to send the |
||
823 | //512 bytes of data read |
||
824 | |||
825 | ptrNextData=(BYTE *)&msd_buffer[0]; |
||
826 | |||
827 | MSDReadState = MSD_READ10_TX_SECTOR; |
||
828 | |||
829 | //Fall through to MSD_READ10_TX_SECTOR |
||
830 | case MSD_READ10_TX_SECTOR: |
||
831 | if(msd_csw.dCSWDataResidue == 0) |
||
832 | { |
||
833 | MSDReadState = MSD_READ10_BLOCK; |
||
834 | break; |
||
835 | } |
||
836 | |||
837 | MSDReadState = MSD_READ10_TX_PACKET; |
||
838 | //Fall through to MSD_READ10_TX_PACKET |
||
839 | |||
840 | case MSD_READ10_TX_PACKET: |
||
841 | if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue>=MSD_IN_EP_SIZE)) |
||
842 | { |
||
843 | /* Write next chunk of data to EP Buffer and send */ |
||
844 | if(USBHandleBusy(USBMSDInHandle)) |
||
845 | { |
||
846 | break; |
||
847 | } |
||
848 | |||
849 | USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,ptrNextData,MSD_IN_EP_SIZE); |
||
850 | |||
851 | MSDReadState = MSD_READ10_TX_SECTOR; |
||
852 | |||
853 | gblCBW.dCBWDataTransferLength-= MSD_IN_EP_SIZE; |
||
854 | msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE; |
||
855 | ptrNextData+=MSD_IN_EP_SIZE; |
||
856 | } |
||
857 | break; |
||
858 | } |
||
859 | |||
860 | return MSDReadState; |
||
861 | } |
||
862 | |||
863 | |||
864 | /****************************************************************************** |
||
865 | Function: |
||
866 | BYTE MSDWriteHandler(void) |
||
867 | |||
868 | Description: |
||
869 | This funtion processes a write command received through |
||
870 | the MSD class driver |
||
871 | |||
872 | PreCondition: |
||
873 | None |
||
874 | |||
875 | Parameters: |
||
876 | None |
||
877 | |||
878 | Return Values: |
||
879 | BYTE - the current state of the MSDWriteHandler state |
||
880 | machine. The valid values are defined in MSD.h under the |
||
881 | MSDWriteHandler state machine declaration section |
||
882 | |||
883 | Remarks: |
||
884 | None |
||
885 | |||
886 | *****************************************************************************/ |
||
887 | BYTE MSDWriteHandler(void) |
||
888 | { |
||
889 | static BYTE MSDWriteState = MSD_WRITE10_WAIT; |
||
890 | |||
891 | switch(MSDWriteState) |
||
892 | { |
||
893 | case MSD_WRITE10_WAIT: |
||
894 | /* Read the LBA, TransferLength fields from Command Block |
||
895 | NOTE: CB is Big-Endian */ |
||
896 | |||
897 | LBA.v[3]=gblCBW.CBWCB[2]; |
||
898 | LBA.v[2]=gblCBW.CBWCB[3]; |
||
899 | LBA.v[1]=gblCBW.CBWCB[4]; |
||
900 | LBA.v[0]=gblCBW.CBWCB[5]; |
||
901 | TransferLength.v[1]=gblCBW.CBWCB[7]; |
||
902 | TransferLength.v[0]=gblCBW.CBWCB[8]; |
||
903 | |||
904 | msd_csw.bCSWStatus=0x0; |
||
905 | |||
906 | MSD_State = MSD_WRITE10_BLOCK; |
||
907 | //Fall through to MSD_WRITE10_BLOCK |
||
908 | case MSD_WRITE10_BLOCK: |
||
909 | if(TransferLength.Val == 0) |
||
910 | { |
||
911 | MSDWriteState = MSD_WRITE10_WAIT; |
||
912 | break; |
||
913 | } |
||
914 | |||
915 | MSDWriteState = MSD_WRITE10_RX_SECTOR; |
||
916 | ptrNextData=(BYTE *)&msd_buffer[0]; |
||
917 | |||
918 | msd_csw.dCSWDataResidue=BLOCKLEN_512; |
||
919 | |||
920 | //Fall through to MSD_WRITE10_RX_SECTOR |
||
921 | case MSD_WRITE10_RX_SECTOR: |
||
922 | { |
||
923 | /* Read 512B into msd_buffer*/ |
||
924 | if(msd_csw.dCSWDataResidue>0) |
||
925 | { |
||
926 | if(USBHandleBusy(USBMSDOutHandle) == TRUE) |
||
927 | { |
||
928 | break; |
||
929 | } |
||
930 | |||
931 | USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP,ptrNextData,MSD_OUT_EP_SIZE); |
||
932 | MSDWriteState = MSD_WRITE10_RX_PACKET; |
||
933 | //Fall through to MSD_WRITE10_RX_PACKET |
||
934 | } |
||
935 | else |
||
936 | { |
||
937 | if(LUNWriteProtectState()) |
||
938 | { |
||
939 | gblSenseData[LUN_INDEX].SenseKey=S_NOT_READY; |
||
940 | gblSenseData[LUN_INDEX].ASC=ASC_WRITE_PROTECTED; |
||
941 | gblSenseData[LUN_INDEX].ASCQ=ASCQ_WRITE_PROTECTED; |
||
942 | msd_csw.bCSWStatus=0x01; |
||
943 | //TODO: (DF) - what state should I return to? |
||
944 | } |
||
945 | else |
||
946 | { |
||
947 | MSDWriteState = MSD_WRITE10_SECTOR; |
||
948 | } |
||
949 | break; |
||
950 | } |
||
951 | } |
||
952 | //Fall through to MSD_WRITE10_RX_PACKET |
||
953 | case MSD_WRITE10_RX_PACKET: |
||
954 | if(USBHandleBusy(USBMSDOutHandle) == TRUE) |
||
955 | { |
||
956 | break; |
||
957 | } |
||
958 | |||
959 | gblCBW.dCBWDataTransferLength-=USBHandleGetLength(USBMSDOutHandle); // 64B read |
||
960 | msd_csw.dCSWDataResidue-=USBHandleGetLength(USBMSDOutHandle); |
||
961 | ptrNextData += MSD_OUT_EP_SIZE; |
||
962 | |||
963 | MSDWriteState = MSD_WRITE10_RX_SECTOR; |
||
964 | break; |
||
965 | case MSD_WRITE10_SECTOR: |
||
966 | { |
||
967 | if(LUNSectorWrite(LBA.Val, (BYTE*)&msd_buffer[0], (LBA.Val==0)?TRUE:FALSE) != TRUE) |
||
968 | { |
||
969 | break; |
||
970 | } |
||
971 | |||
972 | // if (status) { |
||
973 | // msd_csw.bCSWStatus=0x01; |
||
974 | // /* add some sense keys here*/ |
||
975 | // } |
||
976 | |||
977 | LBA.Val++; // One LBA is written. Write the next LBA |
||
978 | TransferLength.Val--; |
||
979 | |||
980 | MSDWriteState = MSD_WRITE10_BLOCK; |
||
981 | break; |
||
982 | } |
||
983 | } |
||
984 | |||
985 | return MSDWriteState; |
||
986 | } |
||
987 | |||
988 | /****************************************************************************** |
||
989 | Function: |
||
990 | void ResetSenseData(void) |
||
991 | |||
992 | Description: |
||
993 | This routine resets the Sense Data, initializing the |
||
994 | structure RequestSenseResponse gblSenseData. |
||
995 | |||
996 | PreCondition: |
||
997 | None |
||
998 | |||
999 | Parameters: |
||
1000 | None |
||
1001 | |||
1002 | Return Values: |
||
1003 | None |
||
1004 | |||
1005 | Remarks: |
||
1006 | None |
||
1007 | |||
1008 | *****************************************************************************/ |
||
1009 | void ResetSenseData(void) |
||
1010 | { |
||
1011 | gblSenseData[LUN_INDEX].ResponseCode=S_CURRENT; |
||
1012 | gblSenseData[LUN_INDEX].VALID=0; // no data in the information field |
||
1013 | gblSenseData[LUN_INDEX].Obsolete=0x0; |
||
1014 | gblSenseData[LUN_INDEX].SenseKey=S_NO_SENSE; |
||
1015 | //gblSenseData.Resv; |
||
1016 | gblSenseData[LUN_INDEX].ILI=0; |
||
1017 | gblSenseData[LUN_INDEX].EOM=0; |
||
1018 | gblSenseData[LUN_INDEX].FILEMARK=0; |
||
1019 | gblSenseData[LUN_INDEX].InformationB0=0x00; |
||
1020 | gblSenseData[LUN_INDEX].InformationB1=0x00; |
||
1021 | gblSenseData[LUN_INDEX].InformationB2=0x00; |
||
1022 | gblSenseData[LUN_INDEX].InformationB3=0x00; |
||
1023 | gblSenseData[LUN_INDEX].AddSenseLen=0x0a; // n-7 (n=17 (0..17)) |
||
1024 | gblSenseData[LUN_INDEX].CmdSpecificInfo.Val=0x0; |
||
1025 | gblSenseData[LUN_INDEX].ASC=0x0; |
||
1026 | gblSenseData[LUN_INDEX].ASCQ=0x0; |
||
1027 | gblSenseData[LUN_INDEX].FRUC=0x0; |
||
1028 | gblSenseData[LUN_INDEX].SenseKeySpecific[0]=0x0; |
||
1029 | gblSenseData[LUN_INDEX].SenseKeySpecific[1]=0x0; |
||
1030 | gblSenseData[LUN_INDEX].SenseKeySpecific[2]=0x0; |
||
1031 | } |
||
1032 | |||
1033 | #endif |
Powered by WebSVN v2.8.3