Dependencies:   ChaNFSSD mbed ChaNFS

Committer:
okini3939
Date:
Thu Nov 10 03:20:42 2011 +0000
Revision:
1:efbcfbae4747
Parent:
0:02c293160df3

        

Who changed what in which revision?

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