Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: KL46Z-lpc81isp lpcterm2
USB_MSD.cpp
00001 /* Copyright (c) 2010-2011 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "USB_MSD.h" 00020 00021 #if (DEBUG2 > 3) 00022 #define MSD_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0); 00023 #else 00024 #define MSD_DBG(...) while(0) 00025 #endif 00026 00027 #define DISK_OK 0x00 00028 #define NO_INIT 0x01 00029 #define NO_DISK 0x02 00030 #define WRITE_PROTECT 0x04 00031 00032 #define CBW_Signature 0x43425355 00033 #define CSW_Signature 0x53425355 00034 00035 // SCSI Commands 00036 #define TEST_UNIT_READY 0x00 00037 #define REQUEST_SENSE 0x03 00038 #define FORMAT_UNIT 0x04 00039 #define INQUIRY 0x12 00040 #define MODE_SELECT6 0x15 00041 #define MODE_SENSE6 0x1A 00042 #define START_STOP_UNIT 0x1B 00043 #define MEDIA_REMOVAL 0x1E 00044 #define READ_FORMAT_CAPACITIES 0x23 00045 #define READ_CAPACITY 0x25 00046 #define READ10 0x28 00047 #define WRITE10 0x2A 00048 #define VERIFY10 0x2F 00049 #define READ12 0xA8 00050 #define WRITE12 0xAA 00051 #define MODE_SELECT10 0x55 00052 #define MODE_SENSE10 0x5A 00053 00054 // MSC class specific requests 00055 #define MSC_REQUEST_RESET 0xFF 00056 #define MSC_REQUEST_GET_MAX_LUN 0xFE 00057 00058 #define DEFAULT_CONFIGURATION (1) 00059 00060 // max packet size 00061 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK 00062 00063 // CSW Status 00064 enum Status { 00065 CSW_PASSED, 00066 CSW_FAILED, 00067 CSW_ERROR, 00068 }; 00069 00070 USB_MSD::USB_MSD(USBDevice* device, DiskInterface* disk) : _device(device),_disk(disk) 00071 { 00072 MSD_DBG("device=%p", device); 00073 00074 stage = READ_CBW; 00075 memset((void *)&cbw, 0, sizeof(CBW)); 00076 memset((void *)&csw, 0, sizeof(CSW)); 00077 page = NULL; 00078 } 00079 00080 bool USB_MSD::connect() { 00081 00082 //disk initialization 00083 if (_disk->disk_status() & NO_INIT) { 00084 if (_disk->disk_initialize()) { 00085 return false; 00086 } 00087 } 00088 00089 // get number of blocks 00090 BlockCount = _disk->disk_sectors(); 00091 00092 // get memory size 00093 MemorySize = _disk->disk_size(); 00094 00095 if (BlockCount > 0) { 00096 BlockSize = MemorySize / BlockCount; 00097 if (BlockSize != 0) { 00098 free(page); 00099 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); 00100 if (page == NULL) 00101 return false; 00102 } 00103 } else { 00104 return false; 00105 } 00106 return true; 00107 } 00108 00109 void USB_MSD::disconnect() { 00110 //De-allocate MSD page size: 00111 free(page); 00112 page = NULL; 00113 } 00114 00115 void USB_MSD::reset() { 00116 stage = READ_CBW; 00117 } 00118 00119 bool USB_MSD::Request_callback(CONTROL_TRANSFER* transfer) 00120 { 00121 static uint8_t msc_maxLUN[1] = {0}; 00122 00123 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { 00124 switch (transfer->setup.bRequest) { 00125 case MSC_REQUEST_RESET: 00126 reset(); 00127 return true; 00128 00129 case MSC_REQUEST_GET_MAX_LUN: 00130 transfer->remaining = 1; 00131 transfer->ptr = msc_maxLUN; 00132 transfer->direction = DEVICE_TO_HOST; 00133 return true; 00134 } 00135 } 00136 return false; 00137 } 00138 00139 // Called in ISR context called when a data is received 00140 bool USB_MSD::EPBULK_OUT_callback() { 00141 uint32_t size = 0; 00142 uint8_t buf[MAX_PACKET_SIZE_EPBULK]; 00143 _device->readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK); 00144 switch (stage) { 00145 // the device has to decode the CBW received 00146 case READ_CBW: 00147 CBWDecode(buf, size); 00148 break; 00149 00150 // the device has to receive data from the host 00151 case PROCESS_CBW: 00152 switch (cbw.CB[0]) { 00153 case WRITE10: 00154 case WRITE12: 00155 memoryWrite(buf, size); 00156 break; 00157 case VERIFY10: 00158 memoryVerify(buf, size); 00159 break; 00160 } 00161 break; 00162 00163 // an error has occured: stall endpoint and send CSW 00164 default: 00165 _device->stallEndpoint(EPBULK_OUT); 00166 csw.Status = CSW_ERROR; 00167 sendCSW(); 00168 break; 00169 } 00170 00171 //reactivate readings on the OUT bulk endpoint 00172 _device->readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00173 return true; 00174 } 00175 00176 // Called in ISR context when a data has been transferred 00177 bool USB_MSD::EPBULK_IN_callback() { 00178 switch (stage) { 00179 00180 // the device has to send data to the host 00181 case PROCESS_CBW: 00182 switch (cbw.CB[0]) { 00183 case READ10: 00184 case READ12: 00185 memoryRead(); 00186 break; 00187 } 00188 break; 00189 00190 //the device has to send a CSW 00191 case SEND_CSW: 00192 sendCSW(); 00193 break; 00194 00195 // the host has received the CSW -> we wait a CBW 00196 case WAIT_CSW: 00197 stage = READ_CBW; 00198 break; 00199 00200 // an error has occured 00201 default: 00202 _device->stallEndpoint(EPBULK_IN); 00203 sendCSW(); 00204 break; 00205 } 00206 return true; 00207 } 00208 00209 void USB_MSD::memoryWrite (uint8_t * buf, uint16_t size) { 00210 00211 if ((addr + size) > MemorySize) { 00212 size = MemorySize - addr; 00213 stage = ERROR; 00214 _device->stallEndpoint(EPBULK_OUT); 00215 } 00216 00217 // we fill an array in RAM of 1 block before writing it in memory 00218 for (int i = 0; i < size; i++) 00219 page[addr%BlockSize + i] = buf[i]; 00220 00221 // if the array is filled, write it in memory 00222 if (!((addr + size)%BlockSize)) { 00223 if (!(_disk->disk_status() & WRITE_PROTECT)) { 00224 _disk->disk_write(page, addr/BlockSize); 00225 } 00226 } 00227 00228 addr += size; 00229 length -= size; 00230 csw.DataResidue -= size; 00231 00232 if ((!length) || (stage != PROCESS_CBW)) { 00233 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; 00234 sendCSW(); 00235 } 00236 } 00237 00238 void USB_MSD::memoryVerify (uint8_t * buf, uint16_t size) { 00239 uint32_t n; 00240 00241 if ((addr + size) > MemorySize) { 00242 size = MemorySize - addr; 00243 stage = ERROR; 00244 _device->stallEndpoint(EPBULK_OUT); 00245 } 00246 00247 // beginning of a new block -> load a whole block in RAM 00248 if (!(addr%BlockSize)) 00249 _disk->disk_read(page, addr/BlockSize); 00250 00251 // info are in RAM -> no need to re-read memory 00252 for (n = 0; n < size; n++) { 00253 if (page[addr%BlockSize + n] != buf[n]) { 00254 memOK = false; 00255 break; 00256 } 00257 } 00258 00259 addr += size; 00260 length -= size; 00261 csw.DataResidue -= size; 00262 00263 if ( !length || (stage != PROCESS_CBW)) { 00264 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; 00265 sendCSW(); 00266 } 00267 } 00268 00269 bool USB_MSD::inquiryRequest (void) { 00270 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00271 36 - 4, 0x80, 0x00, 0x00, 00272 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00273 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00274 '1', '.', '0', ' ', 00275 }; 00276 if (!write(inquiry, sizeof(inquiry))) { 00277 return false; 00278 } 00279 return true; 00280 } 00281 00282 bool USB_MSD::readFormatCapacity() { 00283 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00284 (uint8_t)((BlockCount >> 24) & 0xff), 00285 (uint8_t)((BlockCount >> 16) & 0xff), 00286 (uint8_t)((BlockCount >> 8) & 0xff), 00287 (uint8_t)((BlockCount >> 0) & 0xff), 00288 00289 0x02, 00290 (uint8_t)((BlockSize >> 16) & 0xff), 00291 (uint8_t)((BlockSize >> 8) & 0xff), 00292 (uint8_t)((BlockSize >> 0) & 0xff), 00293 }; 00294 if (!write(capacity, sizeof(capacity))) { 00295 return false; 00296 } 00297 return true; 00298 } 00299 00300 bool USB_MSD::readCapacity (void) { 00301 uint8_t capacity[] = { 00302 (uint8_t)(((BlockCount - 1) >> 24) & 0xff), 00303 (uint8_t)(((BlockCount - 1) >> 16) & 0xff), 00304 (uint8_t)(((BlockCount - 1) >> 8) & 0xff), 00305 (uint8_t)(((BlockCount - 1) >> 0) & 0xff), 00306 00307 (uint8_t)((BlockSize >> 24) & 0xff), 00308 (uint8_t)((BlockSize >> 16) & 0xff), 00309 (uint8_t)((BlockSize >> 8) & 0xff), 00310 (uint8_t)((BlockSize >> 0) & 0xff), 00311 }; 00312 if (!write(capacity, sizeof(capacity))) { 00313 return false; 00314 } 00315 return true; 00316 } 00317 00318 bool USB_MSD::write (uint8_t * buf, uint16_t size) { 00319 00320 if (size >= cbw.DataLength) { 00321 size = cbw.DataLength; 00322 } 00323 stage = SEND_CSW; 00324 00325 if (!_device->writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { 00326 return false; 00327 } 00328 00329 csw.DataResidue -= size; 00330 csw.Status = CSW_PASSED; 00331 return true; 00332 } 00333 00334 bool USB_MSD::modeSense6 (void) { 00335 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00336 if (!write(sense6, sizeof(sense6))) { 00337 return false; 00338 } 00339 return true; 00340 } 00341 00342 void USB_MSD::sendCSW() { 00343 csw.Signature = CSW_Signature; 00344 _device->writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); 00345 stage = WAIT_CSW; 00346 } 00347 00348 bool USB_MSD::requestSense (void) { 00349 uint8_t request_sense[] = { 00350 0x70, 00351 0x00, 00352 0x05, // Sense Key: illegal request 00353 0x00, 00354 0x00, 00355 0x00, 00356 0x00, 00357 0x0A, 00358 0x00, 00359 0x00, 00360 0x00, 00361 0x00, 00362 0x30, 00363 0x01, 00364 0x00, 00365 0x00, 00366 0x00, 00367 0x00, 00368 }; 00369 00370 if (!write(request_sense, sizeof(request_sense))) { 00371 return false; 00372 } 00373 00374 return true; 00375 } 00376 00377 void USB_MSD::fail() { 00378 csw.Status = CSW_FAILED; 00379 sendCSW(); 00380 } 00381 00382 void USB_MSD::CBWDecode(uint8_t * buf, uint16_t size) { 00383 if (size == sizeof(cbw)) { 00384 memcpy((uint8_t *)&cbw, buf, size); 00385 if (cbw.Signature == CBW_Signature) { 00386 csw.Tag = cbw.Tag; 00387 csw.DataResidue = cbw.DataLength; 00388 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { 00389 fail(); 00390 } else { 00391 switch (cbw.CB[0]) { 00392 case TEST_UNIT_READY: 00393 testUnitReady(); 00394 break; 00395 case REQUEST_SENSE: 00396 requestSense(); 00397 break; 00398 case INQUIRY: 00399 inquiryRequest(); 00400 break; 00401 case MODE_SENSE6: 00402 modeSense6(); 00403 break; 00404 case READ_FORMAT_CAPACITIES: 00405 readFormatCapacity(); 00406 break; 00407 case READ_CAPACITY: 00408 readCapacity(); 00409 break; 00410 case READ10: 00411 case READ12: 00412 if (infoTransfer()) { 00413 if ((cbw.Flags & 0x80)) { 00414 stage = PROCESS_CBW; 00415 memoryRead(); 00416 } else { 00417 _device->stallEndpoint(EPBULK_OUT); 00418 csw.Status = CSW_ERROR; 00419 sendCSW(); 00420 } 00421 } 00422 break; 00423 case WRITE10: 00424 case WRITE12: 00425 if (infoTransfer()) { 00426 if (!(cbw.Flags & 0x80)) { 00427 stage = PROCESS_CBW; 00428 } else { 00429 _device->stallEndpoint(EPBULK_IN); 00430 csw.Status = CSW_ERROR; 00431 sendCSW(); 00432 } 00433 } 00434 break; 00435 case VERIFY10: 00436 if (!(cbw.CB[1] & 0x02)) { 00437 csw.Status = CSW_PASSED; 00438 sendCSW(); 00439 break; 00440 } 00441 if (infoTransfer()) { 00442 if (!(cbw.Flags & 0x80)) { 00443 stage = PROCESS_CBW; 00444 memOK = true; 00445 } else { 00446 _device->stallEndpoint(EPBULK_IN); 00447 csw.Status = CSW_ERROR; 00448 sendCSW(); 00449 } 00450 } 00451 break; 00452 case MEDIA_REMOVAL: 00453 csw.Status = CSW_PASSED; 00454 sendCSW(); 00455 break; 00456 default: 00457 fail(); 00458 break; 00459 } 00460 } 00461 } 00462 } 00463 } 00464 00465 void USB_MSD::testUnitReady (void) { 00466 00467 if (cbw.DataLength != 0) { 00468 if ((cbw.Flags & 0x80) != 0) { 00469 _device->stallEndpoint(EPBULK_IN); 00470 } else { 00471 _device->stallEndpoint(EPBULK_OUT); 00472 } 00473 } 00474 00475 csw.Status = CSW_PASSED; 00476 sendCSW(); 00477 } 00478 00479 void USB_MSD::memoryRead (void) { 00480 uint32_t n; 00481 00482 n = (length > MAX_PACKET) ? MAX_PACKET : length; 00483 00484 if ((addr + n) > MemorySize) { 00485 n = MemorySize - addr; 00486 stage = ERROR; 00487 } 00488 00489 // we read an entire block 00490 if (!(addr%BlockSize)) 00491 _disk->disk_read(page, addr/BlockSize); 00492 00493 // write data which are in RAM 00494 _device->writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK); 00495 00496 addr += n; 00497 length -= n; 00498 00499 csw.DataResidue -= n; 00500 00501 if ( !length || (stage != PROCESS_CBW)) { 00502 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; 00503 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; 00504 } 00505 } 00506 00507 bool USB_MSD::infoTransfer (void) { 00508 uint32_t n; 00509 00510 // Logical Block Address of First Block 00511 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); 00512 00513 addr = n * BlockSize; 00514 00515 // Number of Blocks to transfer 00516 switch (cbw.CB[0]) { 00517 case READ10: 00518 case WRITE10: 00519 case VERIFY10: 00520 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); 00521 break; 00522 00523 case READ12: 00524 case WRITE12: 00525 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); 00526 break; 00527 } 00528 00529 length = n * BlockSize; 00530 00531 if (!cbw.DataLength) { // host requests no data 00532 csw.Status = CSW_FAILED; 00533 sendCSW(); 00534 return false; 00535 } 00536 00537 if (cbw.DataLength != length) { 00538 if ((cbw.Flags & 0x80) != 0) { 00539 _device->stallEndpoint(EPBULK_IN); 00540 } else { 00541 _device->stallEndpoint(EPBULK_OUT); 00542 } 00543 00544 csw.Status = CSW_FAILED; 00545 sendCSW(); 00546 return false; 00547 } 00548 00549 return true; 00550 }
Generated on Tue Jul 12 2022 19:39:32 by
1.7.2