EA BaseBoard, playing wav, PC see\'s SD-card through USB port.

Dependencies:   mbed

Committer:
Lerche
Date:
Tue Nov 22 05:45:58 2011 +0000
Revision:
0:fef366d2ed20
Thanks to those who provided EA_WavPlayer and USB_MSC

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Lerche 0:fef366d2ed20 1 /*
Lerche 0:fef366d2ed20 2 LPCUSB, an USB device driver for LPC microcontrollers
Lerche 0:fef366d2ed20 3 Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Lerche 0:fef366d2ed20 4
Lerche 0:fef366d2ed20 5 Redistribution and use in source and binary forms, with or without
Lerche 0:fef366d2ed20 6 modification, are permitted provided that the following conditions are met:
Lerche 0:fef366d2ed20 7
Lerche 0:fef366d2ed20 8 1. Redistributions of source code must retain the above copyright
Lerche 0:fef366d2ed20 9 notice, this list of conditions and the following disclaimer.
Lerche 0:fef366d2ed20 10 2. Redistributions in binary form must reproduce the above copyright
Lerche 0:fef366d2ed20 11 notice, this list of conditions and the following disclaimer in the
Lerche 0:fef366d2ed20 12 documentation and/or other materials provided with the distribution.
Lerche 0:fef366d2ed20 13 3. The name of the author may not be used to endorse or promote products
Lerche 0:fef366d2ed20 14 derived from this software without specific prior written permission.
Lerche 0:fef366d2ed20 15
Lerche 0:fef366d2ed20 16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Lerche 0:fef366d2ed20 17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Lerche 0:fef366d2ed20 18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Lerche 0:fef366d2ed20 19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Lerche 0:fef366d2ed20 20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Lerche 0:fef366d2ed20 21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Lerche 0:fef366d2ed20 22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Lerche 0:fef366d2ed20 23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Lerche 0:fef366d2ed20 24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Lerche 0:fef366d2ed20 25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Lerche 0:fef366d2ed20 26 */
Lerche 0:fef366d2ed20 27
Lerche 0:fef366d2ed20 28 /** @file
Lerche 0:fef366d2ed20 29
Lerche 0:fef366d2ed20 30 Bulk-only-transfer layer for mass storage.
Lerche 0:fef366d2ed20 31
Lerche 0:fef366d2ed20 32 This layers sits between the generic USB layers and the SCSI layer
Lerche 0:fef366d2ed20 33 and performs data transfer according to the BOT protocol.
Lerche 0:fef366d2ed20 34 */
Lerche 0:fef366d2ed20 35
Lerche 0:fef366d2ed20 36 //#define DEBUG
Lerche 0:fef366d2ed20 37 #include "dbg.h"
Lerche 0:fef366d2ed20 38 #include "mbed.h"
Lerche 0:fef366d2ed20 39 #include <string.h>
Lerche 0:fef366d2ed20 40
Lerche 0:fef366d2ed20 41 #include "msc_bot.h"
Lerche 0:fef366d2ed20 42 #include "msc_scsi.h"
Lerche 0:fef366d2ed20 43 #include "USBMSC.h"
Lerche 0:fef366d2ed20 44
Lerche 0:fef366d2ed20 45 extern USBMSC usbdev;
Lerche 0:fef366d2ed20 46
Lerche 0:fef366d2ed20 47 /** Command block wrapper structure */
Lerche 0:fef366d2ed20 48 struct TCBW {
Lerche 0:fef366d2ed20 49 uint32_t dwCBWSignature;
Lerche 0:fef366d2ed20 50 uint32_t dwCBWTag;
Lerche 0:fef366d2ed20 51 uint32_t dwCBWDataTransferLength;
Lerche 0:fef366d2ed20 52 uint8_t bmCBWFlags;
Lerche 0:fef366d2ed20 53 uint8_t bCBWLun;
Lerche 0:fef366d2ed20 54 uint8_t bCBWCBLength;
Lerche 0:fef366d2ed20 55 uint8_t CBWCB[16];
Lerche 0:fef366d2ed20 56 uint8_t dummy[MAX_PACKET_SIZE_EPBULK - 31];
Lerche 0:fef366d2ed20 57 } __attribute__((packed));
Lerche 0:fef366d2ed20 58
Lerche 0:fef366d2ed20 59 /** Command status wrapper structure */
Lerche 0:fef366d2ed20 60 struct TCSW {
Lerche 0:fef366d2ed20 61 uint32_t dwCSWSignature;
Lerche 0:fef366d2ed20 62 uint32_t dwCSWTag;
Lerche 0:fef366d2ed20 63 uint32_t dwCSWDataResidue;
Lerche 0:fef366d2ed20 64 uint8_t bmCSWStatus;
Lerche 0:fef366d2ed20 65 uint8_t dummy[MAX_PACKET_SIZE_EPBULK - 13];
Lerche 0:fef366d2ed20 66 } __attribute__((packed));
Lerche 0:fef366d2ed20 67
Lerche 0:fef366d2ed20 68 /** States of BOT state machine */
Lerche 0:fef366d2ed20 69 typedef enum {
Lerche 0:fef366d2ed20 70 eCBW,
Lerche 0:fef366d2ed20 71 eDataOut,
Lerche 0:fef366d2ed20 72 eDataIn,
Lerche 0:fef366d2ed20 73 eCSW,
Lerche 0:fef366d2ed20 74 eStalled
Lerche 0:fef366d2ed20 75 } EBotState;
Lerche 0:fef366d2ed20 76
Lerche 0:fef366d2ed20 77
Lerche 0:fef366d2ed20 78 #define CBW_SIGNATURE 0x43425355 /**< magic word in CBW */
Lerche 0:fef366d2ed20 79 #define CSW_SIGNATURE 0x53425355 /**< magic word in CSW */
Lerche 0:fef366d2ed20 80
Lerche 0:fef366d2ed20 81 #define STATUS_PASSED 0x00 /**< successful transfer */
Lerche 0:fef366d2ed20 82 #define STATUS_FAILED 0x01 /**< failed transfer */
Lerche 0:fef366d2ed20 83 #define STATUS_PHASE_ERR 0x02 /**< conflict between host and device */
Lerche 0:fef366d2ed20 84
Lerche 0:fef366d2ed20 85 static uint32_t dwTransferSize; /**< total size of data transfer */
Lerche 0:fef366d2ed20 86 static uint32_t dwOffset; /**< offset in current data transfer */
Lerche 0:fef366d2ed20 87
Lerche 0:fef366d2ed20 88 static TCBW CBW;
Lerche 0:fef366d2ed20 89 static TCSW CSW;
Lerche 0:fef366d2ed20 90
Lerche 0:fef366d2ed20 91 static EBotState eState;
Lerche 0:fef366d2ed20 92
Lerche 0:fef366d2ed20 93 static uint8_t *pbData;
Lerche 0:fef366d2ed20 94
Lerche 0:fef366d2ed20 95
Lerche 0:fef366d2ed20 96
Lerche 0:fef366d2ed20 97 /**
Lerche 0:fef366d2ed20 98 Resets the BOT state machine
Lerche 0:fef366d2ed20 99 */
Lerche 0:fef366d2ed20 100 void MSCBotReset(void)
Lerche 0:fef366d2ed20 101 {
Lerche 0:fef366d2ed20 102 DBG("BOT reset in state %d\n", eState);
Lerche 0:fef366d2ed20 103 // reset BOT state
Lerche 0:fef366d2ed20 104 eState = eCBW;
Lerche 0:fef366d2ed20 105 // reset SCSI
Lerche 0:fef366d2ed20 106 SCSIReset();
Lerche 0:fef366d2ed20 107 }
Lerche 0:fef366d2ed20 108
Lerche 0:fef366d2ed20 109
Lerche 0:fef366d2ed20 110 /**
Lerche 0:fef366d2ed20 111 Prepares a CSW, to be sent on next bulk-IN interrupt
Lerche 0:fef366d2ed20 112
Lerche 0:fef366d2ed20 113 @param [in] bStatus CSW status
Lerche 0:fef366d2ed20 114 */
Lerche 0:fef366d2ed20 115 static void SendCSW(uint8_t bStatus)
Lerche 0:fef366d2ed20 116 {
Lerche 0:fef366d2ed20 117 int iResidue;
Lerche 0:fef366d2ed20 118
Lerche 0:fef366d2ed20 119 iResidue = CBW.dwCBWDataTransferLength - dwTransferSize;
Lerche 0:fef366d2ed20 120
Lerche 0:fef366d2ed20 121 // construct CSW
Lerche 0:fef366d2ed20 122 CSW.dwCSWSignature = CSW_SIGNATURE;
Lerche 0:fef366d2ed20 123 CSW.dwCSWTag = CBW.dwCBWTag;
Lerche 0:fef366d2ed20 124 CSW.dwCSWDataResidue = MAX(iResidue, 0);
Lerche 0:fef366d2ed20 125 CSW.bmCSWStatus = bStatus;
Lerche 0:fef366d2ed20 126
Lerche 0:fef366d2ed20 127 DBG("CSW: status=%x, residue=%d\n", bStatus, CSW.dwCSWDataResidue);
Lerche 0:fef366d2ed20 128
Lerche 0:fef366d2ed20 129 // next state
Lerche 0:fef366d2ed20 130 eState = eCSW;
Lerche 0:fef366d2ed20 131 }
Lerche 0:fef366d2ed20 132
Lerche 0:fef366d2ed20 133
Lerche 0:fef366d2ed20 134 /**
Lerche 0:fef366d2ed20 135 Checks if CBW is valid and meaningful
Lerche 0:fef366d2ed20 136
Lerche 0:fef366d2ed20 137 @param [in] pCBW Command block wrapper
Lerche 0:fef366d2ed20 138 @param [in] iLen Length of CBW
Lerche 0:fef366d2ed20 139
Lerche 0:fef366d2ed20 140 @return true if valid and meaningful
Lerche 0:fef366d2ed20 141 */
Lerche 0:fef366d2ed20 142 static bool CheckCBW(TCBW *pCBW, int iLen)
Lerche 0:fef366d2ed20 143 {
Lerche 0:fef366d2ed20 144 // CBW valid?
Lerche 0:fef366d2ed20 145 if (iLen != 31) {
Lerche 0:fef366d2ed20 146 DBG("Invalid length (%d)\n", iLen);
Lerche 0:fef366d2ed20 147 return false;
Lerche 0:fef366d2ed20 148 }
Lerche 0:fef366d2ed20 149 if (pCBW->dwCBWSignature != CBW_SIGNATURE) {
Lerche 0:fef366d2ed20 150 DBG("Invalid signature %x\n", pCBW->dwCBWSignature);
Lerche 0:fef366d2ed20 151 return false;
Lerche 0:fef366d2ed20 152 }
Lerche 0:fef366d2ed20 153
Lerche 0:fef366d2ed20 154 // CBW meaningful?
Lerche 0:fef366d2ed20 155 if (pCBW->bCBWLun != 0) {
Lerche 0:fef366d2ed20 156 DBG("Invalid LUN %d\n", pCBW->bCBWLun);
Lerche 0:fef366d2ed20 157 return false;
Lerche 0:fef366d2ed20 158 }
Lerche 0:fef366d2ed20 159 if ((pCBW->bCBWCBLength < 1) || (pCBW->bCBWCBLength > 16)) {
Lerche 0:fef366d2ed20 160 DBG("Invalid CB len %d\n", pCBW->bCBWCBLength);
Lerche 0:fef366d2ed20 161 return false;
Lerche 0:fef366d2ed20 162 }
Lerche 0:fef366d2ed20 163 return true;
Lerche 0:fef366d2ed20 164 }
Lerche 0:fef366d2ed20 165
Lerche 0:fef366d2ed20 166
Lerche 0:fef366d2ed20 167 /*************************************************************************
Lerche 0:fef366d2ed20 168 BOTStall
Lerche 0:fef366d2ed20 169 ========
Lerche 0:fef366d2ed20 170 Local function to stall ongoing transfer
Lerche 0:fef366d2ed20 171
Lerche 0:fef366d2ed20 172 Which endpoint to stall is determined by looking at the transfer
Lerche 0:fef366d2ed20 173 direction intended by the host.
Lerche 0:fef366d2ed20 174
Lerche 0:fef366d2ed20 175 **************************************************************************/
Lerche 0:fef366d2ed20 176 static void BOTStall(void)
Lerche 0:fef366d2ed20 177 {
Lerche 0:fef366d2ed20 178 if ((CBW.bmCBWFlags & 0x80) || (CBW.dwCBWDataTransferLength == 0)) {
Lerche 0:fef366d2ed20 179 // stall data-in or CSW
Lerche 0:fef366d2ed20 180 usbdev.stallEndpoint(EPBULK_IN);
Lerche 0:fef366d2ed20 181 }
Lerche 0:fef366d2ed20 182 else {
Lerche 0:fef366d2ed20 183 // stall data-out
Lerche 0:fef366d2ed20 184 usbdev.stallEndpoint(EPBULK_OUT);
Lerche 0:fef366d2ed20 185 }
Lerche 0:fef366d2ed20 186 }
Lerche 0:fef366d2ed20 187
Lerche 0:fef366d2ed20 188
Lerche 0:fef366d2ed20 189 /*************************************************************************
Lerche 0:fef366d2ed20 190 HandleDataIn
Lerche 0:fef366d2ed20 191 ============
Lerche 0:fef366d2ed20 192 Handles data from device-to-host
Lerche 0:fef366d2ed20 193
Lerche 0:fef366d2ed20 194 **************************************************************************/
Lerche 0:fef366d2ed20 195 static void HandleDataIn(int io)
Lerche 0:fef366d2ed20 196 {
Lerche 0:fef366d2ed20 197 int iChunk;
Lerche 0:fef366d2ed20 198 // process data for host in SCSI layer
Lerche 0:fef366d2ed20 199 pbData = SCSIHandleData(CBW.CBWCB, CBW.bCBWCBLength, pbData, dwOffset);
Lerche 0:fef366d2ed20 200 if (pbData == NULL) {
Lerche 0:fef366d2ed20 201 BOTStall();
Lerche 0:fef366d2ed20 202 SendCSW(STATUS_FAILED);
Lerche 0:fef366d2ed20 203 return;
Lerche 0:fef366d2ed20 204 }
Lerche 0:fef366d2ed20 205
Lerche 0:fef366d2ed20 206 // send data to host?
Lerche 0:fef366d2ed20 207 if (dwOffset < dwTransferSize) {
Lerche 0:fef366d2ed20 208 iChunk = MIN(64, dwTransferSize - dwOffset);
Lerche 0:fef366d2ed20 209 //USBHwEPWrite(MSC_BULK_IN_EP, pbData, iChunk);
Lerche 0:fef366d2ed20 210 usbdev.writeNB(EPBULK_IN, pbData, iChunk, MAX_PACKET_SIZE_EPBULK);
Lerche 0:fef366d2ed20 211 dwOffset += iChunk;
Lerche 0:fef366d2ed20 212 }
Lerche 0:fef366d2ed20 213
Lerche 0:fef366d2ed20 214 // are we done now?
Lerche 0:fef366d2ed20 215 if (dwOffset == dwTransferSize) {
Lerche 0:fef366d2ed20 216 if (dwOffset != CBW.dwCBWDataTransferLength) {
Lerche 0:fef366d2ed20 217 // stall pipe
Lerche 0:fef366d2ed20 218 DBG("stalling DIN");
Lerche 0:fef366d2ed20 219 BOTStall();
Lerche 0:fef366d2ed20 220 }
Lerche 0:fef366d2ed20 221 // done
Lerche 0:fef366d2ed20 222 SendCSW(STATUS_PASSED);
Lerche 0:fef366d2ed20 223 }
Lerche 0:fef366d2ed20 224 }
Lerche 0:fef366d2ed20 225
Lerche 0:fef366d2ed20 226
Lerche 0:fef366d2ed20 227 /*************************************************************************
Lerche 0:fef366d2ed20 228 HandleDataOut
Lerche 0:fef366d2ed20 229 =============
Lerche 0:fef366d2ed20 230 Handles data from host-to-device
Lerche 0:fef366d2ed20 231
Lerche 0:fef366d2ed20 232 **************************************************************************/
Lerche 0:fef366d2ed20 233 static void HandleDataOut(void)
Lerche 0:fef366d2ed20 234 {
Lerche 0:fef366d2ed20 235 int iChunk;
Lerche 0:fef366d2ed20 236
Lerche 0:fef366d2ed20 237 if (dwOffset < dwTransferSize) {
Lerche 0:fef366d2ed20 238 // get data from host
Lerche 0:fef366d2ed20 239 // iChunk = USBHwEPRead(MSC_BULK_OUT_EP, pbData, dwTransferSize - dwOffset);
Lerche 0:fef366d2ed20 240 usbdev.read(EPBULK_OUT, pbData, (uint16_t*)&iChunk, MAX_PACKET_SIZE_EPBULK);
Lerche 0:fef366d2ed20 241 // process data in SCSI layer
Lerche 0:fef366d2ed20 242 pbData = SCSIHandleData(CBW.CBWCB, CBW.bCBWCBLength, pbData, dwOffset);
Lerche 0:fef366d2ed20 243 if (pbData == NULL) {
Lerche 0:fef366d2ed20 244 BOTStall();
Lerche 0:fef366d2ed20 245 SendCSW(STATUS_FAILED);
Lerche 0:fef366d2ed20 246 return;
Lerche 0:fef366d2ed20 247 }
Lerche 0:fef366d2ed20 248 dwOffset += iChunk;
Lerche 0:fef366d2ed20 249 }
Lerche 0:fef366d2ed20 250
Lerche 0:fef366d2ed20 251 // are we done now?
Lerche 0:fef366d2ed20 252 if (dwOffset == dwTransferSize) {
Lerche 0:fef366d2ed20 253 if (dwOffset != CBW.dwCBWDataTransferLength) {
Lerche 0:fef366d2ed20 254 // stall pipe
Lerche 0:fef366d2ed20 255 DBG("stalling DOUT");
Lerche 0:fef366d2ed20 256 BOTStall();
Lerche 0:fef366d2ed20 257 }
Lerche 0:fef366d2ed20 258 SendCSW(STATUS_PASSED);
Lerche 0:fef366d2ed20 259 }
Lerche 0:fef366d2ed20 260 }
Lerche 0:fef366d2ed20 261
Lerche 0:fef366d2ed20 262
Lerche 0:fef366d2ed20 263 /**
Lerche 0:fef366d2ed20 264 Handles the BOT bulk OUT endpoint
Lerche 0:fef366d2ed20 265
Lerche 0:fef366d2ed20 266 @param [in] bEP Endpoint number
Lerche 0:fef366d2ed20 267 @param [in] bEPStatus Endpoint status (indicates NAK, STALL, etc)
Lerche 0:fef366d2ed20 268
Lerche 0:fef366d2ed20 269 */
Lerche 0:fef366d2ed20 270 void MSCBotBulkOut()
Lerche 0:fef366d2ed20 271 {
Lerche 0:fef366d2ed20 272 int iLen, iChunk;
Lerche 0:fef366d2ed20 273 bool fHostIn, fDevIn;
Lerche 0:fef366d2ed20 274
Lerche 0:fef366d2ed20 275 switch (eState) {
Lerche 0:fef366d2ed20 276
Lerche 0:fef366d2ed20 277 case eCBW:
Lerche 0:fef366d2ed20 278 //iLen = USBHwEPRead(bEP, (U8 *)&CBW, sizeof(CBW));
Lerche 0:fef366d2ed20 279 usbdev.read(EPBULK_OUT, (uint8_t *)&CBW, (uint16_t*)&iLen, MAX_PACKET_SIZE_EPBULK);
Lerche 0:fef366d2ed20 280
Lerche 0:fef366d2ed20 281 // check if we got a good CBW
Lerche 0:fef366d2ed20 282 if (!CheckCBW(&CBW, iLen)) {
Lerche 0:fef366d2ed20 283 // see 6.6.1
Lerche 0:fef366d2ed20 284 usbdev.stallEndpoint(EPBULK_IN);
Lerche 0:fef366d2ed20 285 usbdev.stallEndpoint(EPBULK_OUT);
Lerche 0:fef366d2ed20 286 eState = eStalled;
Lerche 0:fef366d2ed20 287 break;
Lerche 0:fef366d2ed20 288 }
Lerche 0:fef366d2ed20 289
Lerche 0:fef366d2ed20 290 DBG("CBW: len=%d, flags=%x, cmd=%x, cmdlen=%d\n",
Lerche 0:fef366d2ed20 291 CBW.dwCBWDataTransferLength, CBW.bmCBWFlags, CBW.CBWCB[0], CBW.bCBWCBLength);
Lerche 0:fef366d2ed20 292
Lerche 0:fef366d2ed20 293 dwOffset = 0;
Lerche 0:fef366d2ed20 294 dwTransferSize = 0;
Lerche 0:fef366d2ed20 295 fHostIn = ((CBW.bmCBWFlags & 0x80) != 0);
Lerche 0:fef366d2ed20 296
Lerche 0:fef366d2ed20 297 // verify request
Lerche 0:fef366d2ed20 298 pbData = SCSIHandleCmd(CBW.CBWCB, CBW.bCBWCBLength, &iLen, &fDevIn);
Lerche 0:fef366d2ed20 299 if (pbData == NULL) {
Lerche 0:fef366d2ed20 300 // unknown command
Lerche 0:fef366d2ed20 301 BOTStall();
Lerche 0:fef366d2ed20 302 SendCSW(STATUS_FAILED);
Lerche 0:fef366d2ed20 303 break;
Lerche 0:fef366d2ed20 304 }
Lerche 0:fef366d2ed20 305
Lerche 0:fef366d2ed20 306 // rule: if device and host disagree on direction, send CSW with status 2
Lerche 0:fef366d2ed20 307 if ((iLen > 0) &&
Lerche 0:fef366d2ed20 308 ((fHostIn && !fDevIn) ||
Lerche 0:fef366d2ed20 309 (!fHostIn && fDevIn))) {
Lerche 0:fef366d2ed20 310 DBG("Host and device disagree on direction\n");
Lerche 0:fef366d2ed20 311 BOTStall();
Lerche 0:fef366d2ed20 312 SendCSW(STATUS_PHASE_ERR);
Lerche 0:fef366d2ed20 313 break;
Lerche 0:fef366d2ed20 314 }
Lerche 0:fef366d2ed20 315
Lerche 0:fef366d2ed20 316 // rule: if D > H, send CSW with status 2
Lerche 0:fef366d2ed20 317 if (iLen > CBW.dwCBWDataTransferLength) {
Lerche 0:fef366d2ed20 318 DBG("Negative residue\n");
Lerche 0:fef366d2ed20 319 BOTStall();
Lerche 0:fef366d2ed20 320 SendCSW(STATUS_PHASE_ERR);
Lerche 0:fef366d2ed20 321 break;
Lerche 0:fef366d2ed20 322 }
Lerche 0:fef366d2ed20 323
Lerche 0:fef366d2ed20 324 dwTransferSize = iLen;
Lerche 0:fef366d2ed20 325 if ((dwTransferSize == 0) || fDevIn) {
Lerche 0:fef366d2ed20 326 // data from device-to-host
Lerche 0:fef366d2ed20 327 eState = eDataIn;
Lerche 0:fef366d2ed20 328 HandleDataIn(0);
Lerche 0:fef366d2ed20 329 }
Lerche 0:fef366d2ed20 330 else {
Lerche 0:fef366d2ed20 331 // data from host-to-device
Lerche 0:fef366d2ed20 332 eState = eDataOut;
Lerche 0:fef366d2ed20 333 }
Lerche 0:fef366d2ed20 334 break;
Lerche 0:fef366d2ed20 335
Lerche 0:fef366d2ed20 336 case eDataOut:
Lerche 0:fef366d2ed20 337 HandleDataOut();
Lerche 0:fef366d2ed20 338 break;
Lerche 0:fef366d2ed20 339
Lerche 0:fef366d2ed20 340 case eDataIn:
Lerche 0:fef366d2ed20 341 case eCSW:
Lerche 0:fef366d2ed20 342 // iChunk = USBHwEPRead(bEP, NULL, 0);
Lerche 0:fef366d2ed20 343 uint8_t dummy[64];
Lerche 0:fef366d2ed20 344 int idummy;
Lerche 0:fef366d2ed20 345 usbdev.read(EPBULK_OUT, dummy, (uint16_t*)&idummy, MAX_PACKET_SIZE_EPBULK);
Lerche 0:fef366d2ed20 346 DBG("Phase error in state %d, %d bytes\n", eState, iChunk);
Lerche 0:fef366d2ed20 347 eState = eCBW;
Lerche 0:fef366d2ed20 348 break;
Lerche 0:fef366d2ed20 349
Lerche 0:fef366d2ed20 350 case eStalled:
Lerche 0:fef366d2ed20 351 // keep stalling
Lerche 0:fef366d2ed20 352 usbdev.stallEndpoint(EPBULK_OUT);
Lerche 0:fef366d2ed20 353 break;
Lerche 0:fef366d2ed20 354
Lerche 0:fef366d2ed20 355 default:
Lerche 0:fef366d2ed20 356 DBG("Invalid state %d\n", eState);
Lerche 0:fef366d2ed20 357 break;
Lerche 0:fef366d2ed20 358 }
Lerche 0:fef366d2ed20 359 }
Lerche 0:fef366d2ed20 360
Lerche 0:fef366d2ed20 361
Lerche 0:fef366d2ed20 362 /**
Lerche 0:fef366d2ed20 363 Handles the BOT bulk IN endpoint
Lerche 0:fef366d2ed20 364
Lerche 0:fef366d2ed20 365 @param [in] bEP Endpoint number
Lerche 0:fef366d2ed20 366 @param [in] bEPStatus Endpoint status (indicates NAK, STALL, etc)
Lerche 0:fef366d2ed20 367
Lerche 0:fef366d2ed20 368 */
Lerche 0:fef366d2ed20 369 void MSCBotBulkIn()
Lerche 0:fef366d2ed20 370 {
Lerche 0:fef366d2ed20 371 DBG("MSCBotBulkIn: %d\r\n", eState);
Lerche 0:fef366d2ed20 372 switch (eState) {
Lerche 0:fef366d2ed20 373
Lerche 0:fef366d2ed20 374 case eCBW:
Lerche 0:fef366d2ed20 375 case eDataOut:
Lerche 0:fef366d2ed20 376 // ignore possibly old ACKs
Lerche 0:fef366d2ed20 377 break;
Lerche 0:fef366d2ed20 378
Lerche 0:fef366d2ed20 379 case eDataIn:
Lerche 0:fef366d2ed20 380 HandleDataIn(1);
Lerche 0:fef366d2ed20 381 break;
Lerche 0:fef366d2ed20 382
Lerche 0:fef366d2ed20 383 case eCSW:
Lerche 0:fef366d2ed20 384 // wait for an IN token, then send the CSW
Lerche 0:fef366d2ed20 385 //USBHwEPWrite(MSC_BULK_IN_EP, (uint8_t *)&CSW, 13);
Lerche 0:fef366d2ed20 386 usbdev.writeNB(EPBULK_IN, (uint8_t *)&CSW, 13, MAX_PACKET_SIZE_EPBULK);
Lerche 0:fef366d2ed20 387 eState = eCBW;
Lerche 0:fef366d2ed20 388 break;
Lerche 0:fef366d2ed20 389
Lerche 0:fef366d2ed20 390 case eStalled:
Lerche 0:fef366d2ed20 391 // keep stalling
Lerche 0:fef366d2ed20 392 usbdev.stallEndpoint(EPBULK_IN);
Lerche 0:fef366d2ed20 393 break;
Lerche 0:fef366d2ed20 394
Lerche 0:fef366d2ed20 395 default:
Lerche 0:fef366d2ed20 396 DBG("Invalid state %d\n", eState);
Lerche 0:fef366d2ed20 397 break;
Lerche 0:fef366d2ed20 398 }
Lerche 0:fef366d2ed20 399 }
Lerche 0:fef366d2ed20 400