USB composite device example program, drag-and-drop flash writer.
Dependencies: SWD USBDevice mbed BaseDAP
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 "stdint.h" 00020 #include "USB_MSD.h" 00021 00022 #define DISK_OK 0x00 00023 #define NO_INIT 0x01 00024 #define NO_DISK 0x02 00025 #define WRITE_PROTECT 0x04 00026 00027 #define CBW_Signature 0x43425355 00028 #define CSW_Signature 0x53425355 00029 00030 // SCSI Commands 00031 #define TEST_UNIT_READY 0x00 00032 #define REQUEST_SENSE 0x03 00033 #define FORMAT_UNIT 0x04 00034 #define INQUIRY 0x12 00035 #define MODE_SELECT6 0x15 00036 #define MODE_SENSE6 0x1A 00037 #define START_STOP_UNIT 0x1B 00038 #define MEDIA_REMOVAL 0x1E 00039 #define READ_FORMAT_CAPACITIES 0x23 00040 #define READ_CAPACITY 0x25 00041 #define READ10 0x28 00042 #define WRITE10 0x2A 00043 #define VERIFY10 0x2F 00044 #define READ12 0xA8 00045 #define WRITE12 0xAA 00046 #define MODE_SELECT10 0x55 00047 #define MODE_SENSE10 0x5A 00048 00049 // MSC class specific requests 00050 #define MSC_REQUEST_RESET 0xFF 00051 #define MSC_REQUEST_GET_MAX_LUN 0xFE 00052 00053 #define DEFAULT_CONFIGURATION (1) 00054 00055 // max packet size 00056 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK 00057 00058 // CSW Status 00059 enum Status { 00060 CSW_PASSED, 00061 CSW_FAILED, 00062 CSW_ERROR, 00063 }; 00064 00065 USB_MSD::USB_MSD(USBMSD2* device, USBMSD2* disk) : _device(device),_disk(device) 00066 { 00067 stage = READ_CBW; 00068 memset((void *)&cbw, 0, sizeof(CBW)); 00069 memset((void *)&csw, 0, sizeof(CSW)); 00070 page = NULL; 00071 } 00072 00073 bool USB_MSD::connect() { 00074 00075 //disk initialization 00076 if (_disk->disk_status() & NO_INIT) { 00077 if (_disk->disk_initialize()) { 00078 return false; 00079 } 00080 } 00081 00082 // get number of blocks 00083 BlockCount = _disk->disk_sectors(); 00084 00085 // get memory size 00086 MemorySize = _disk->disk_size(); 00087 00088 if (BlockCount > 0) { 00089 BlockSize = MemorySize / BlockCount; 00090 if (BlockSize != 0) { 00091 free(page); 00092 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); 00093 if (page == NULL) 00094 return false; 00095 } 00096 } else { 00097 return false; 00098 } 00099 return true; 00100 } 00101 00102 void USB_MSD::disconnect() { 00103 //De-allocate MSD page size: 00104 free(page); 00105 page = NULL; 00106 } 00107 00108 void USB_MSD::reset() { 00109 stage = READ_CBW; 00110 } 00111 00112 bool USB_MSD::Request_callback(CONTROL_TRANSFER* transfer) 00113 { 00114 static uint8_t msc_maxLUN[1] = {0}; 00115 00116 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { 00117 switch (transfer->setup.bRequest) { 00118 case MSC_REQUEST_RESET: 00119 reset(); 00120 return true; 00121 00122 case MSC_REQUEST_GET_MAX_LUN: 00123 transfer->remaining = 1; 00124 transfer->ptr = msc_maxLUN; 00125 transfer->direction = DEVICE_TO_HOST; 00126 return true; 00127 } 00128 } 00129 return false; 00130 } 00131 00132 // Called in ISR context called when a data is received 00133 bool USB_MSD::EPBULK_OUT_callback() { 00134 uint32_t size = 0; 00135 uint8_t buf[MAX_PACKET_SIZE_EPBULK]; 00136 _device->readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK); 00137 switch (stage) { 00138 // the device has to decode the CBW received 00139 case READ_CBW: 00140 CBWDecode(buf, size); 00141 break; 00142 00143 // the device has to receive data from the host 00144 case PROCESS_CBW: 00145 switch (cbw.CB[0]) { 00146 case WRITE10: 00147 case WRITE12: 00148 memoryWrite(buf, size); 00149 break; 00150 case VERIFY10: 00151 memoryVerify(buf, size); 00152 break; 00153 } 00154 break; 00155 00156 // an error has occured: stall endpoint and send CSW 00157 default: 00158 _device->stallEndpoint(EPBULK_OUT); 00159 csw.Status = CSW_ERROR; 00160 sendCSW(); 00161 break; 00162 } 00163 00164 //reactivate readings on the OUT bulk endpoint 00165 _device->readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00166 return true; 00167 } 00168 00169 // Called in ISR context when a data has been transferred 00170 bool USB_MSD::EPBULK_IN_callback() { 00171 switch (stage) { 00172 00173 // the device has to send data to the host 00174 case PROCESS_CBW: 00175 switch (cbw.CB[0]) { 00176 case READ10: 00177 case READ12: 00178 memoryRead(); 00179 break; 00180 } 00181 break; 00182 00183 //the device has to send a CSW 00184 case SEND_CSW: 00185 sendCSW(); 00186 break; 00187 00188 // the host has received the CSW -> we wait a CBW 00189 case WAIT_CSW: 00190 stage = READ_CBW; 00191 break; 00192 00193 // an error has occured 00194 default: 00195 _device->stallEndpoint(EPBULK_IN); 00196 sendCSW(); 00197 break; 00198 } 00199 return true; 00200 } 00201 00202 void USB_MSD::memoryWrite (uint8_t * buf, uint16_t size) { 00203 00204 if ((addr + size) > MemorySize) { 00205 size = MemorySize - addr; 00206 stage = ERROR; 00207 _device->stallEndpoint(EPBULK_OUT); 00208 } 00209 00210 // we fill an array in RAM of 1 block before writing it in memory 00211 for (int i = 0; i < size; i++) 00212 page[addr%BlockSize + i] = buf[i]; 00213 00214 // if the array is filled, write it in memory 00215 if (!((addr + size)%BlockSize)) { 00216 if (!(_disk->disk_status() & WRITE_PROTECT)) { 00217 _disk->disk_write(page, addr/BlockSize); 00218 } 00219 } 00220 00221 addr += size; 00222 length -= size; 00223 csw.DataResidue -= size; 00224 00225 if ((!length) || (stage != PROCESS_CBW)) { 00226 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; 00227 sendCSW(); 00228 } 00229 } 00230 00231 void USB_MSD::memoryVerify (uint8_t * buf, uint16_t size) { 00232 uint32_t n; 00233 00234 if ((addr + size) > MemorySize) { 00235 size = MemorySize - addr; 00236 stage = ERROR; 00237 _device->stallEndpoint(EPBULK_OUT); 00238 } 00239 00240 // beginning of a new block -> load a whole block in RAM 00241 if (!(addr%BlockSize)) 00242 _disk->disk_read(page, addr/BlockSize); 00243 00244 // info are in RAM -> no need to re-read memory 00245 for (n = 0; n < size; n++) { 00246 if (page[addr%BlockSize + n] != buf[n]) { 00247 memOK = false; 00248 break; 00249 } 00250 } 00251 00252 addr += size; 00253 length -= size; 00254 csw.DataResidue -= size; 00255 00256 if ( !length || (stage != PROCESS_CBW)) { 00257 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; 00258 sendCSW(); 00259 } 00260 } 00261 00262 bool USB_MSD::inquiryRequest (void) { 00263 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00264 36 - 4, 0x80, 0x00, 0x00, 00265 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00266 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00267 '1', '.', '0', ' ', 00268 }; 00269 if (!write(inquiry, sizeof(inquiry))) { 00270 return false; 00271 } 00272 return true; 00273 } 00274 00275 bool USB_MSD::readFormatCapacity() { 00276 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00277 (uint8_t)((BlockCount >> 24) & 0xff), 00278 (uint8_t)((BlockCount >> 16) & 0xff), 00279 (uint8_t)((BlockCount >> 8) & 0xff), 00280 (uint8_t)((BlockCount >> 0) & 0xff), 00281 00282 0x02, 00283 (uint8_t)((BlockSize >> 16) & 0xff), 00284 (uint8_t)((BlockSize >> 8) & 0xff), 00285 (uint8_t)((BlockSize >> 0) & 0xff), 00286 }; 00287 if (!write(capacity, sizeof(capacity))) { 00288 return false; 00289 } 00290 return true; 00291 } 00292 00293 bool USB_MSD::readCapacity (void) { 00294 uint8_t capacity[] = { 00295 (uint8_t)(((BlockCount - 1) >> 24) & 0xff), 00296 (uint8_t)(((BlockCount - 1) >> 16) & 0xff), 00297 (uint8_t)(((BlockCount - 1) >> 8) & 0xff), 00298 (uint8_t)(((BlockCount - 1) >> 0) & 0xff), 00299 00300 (uint8_t)((BlockSize >> 24) & 0xff), 00301 (uint8_t)((BlockSize >> 16) & 0xff), 00302 (uint8_t)((BlockSize >> 8) & 0xff), 00303 (uint8_t)((BlockSize >> 0) & 0xff), 00304 }; 00305 if (!write(capacity, sizeof(capacity))) { 00306 return false; 00307 } 00308 return true; 00309 } 00310 00311 bool USB_MSD::write (uint8_t * buf, uint16_t size) { 00312 00313 if (size >= cbw.DataLength) { 00314 size = cbw.DataLength; 00315 } 00316 stage = SEND_CSW; 00317 00318 if (!_device->writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { 00319 return false; 00320 } 00321 00322 csw.DataResidue -= size; 00323 csw.Status = CSW_PASSED; 00324 return true; 00325 } 00326 00327 bool USB_MSD::modeSense6 (void) { 00328 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00329 if (!write(sense6, sizeof(sense6))) { 00330 return false; 00331 } 00332 return true; 00333 } 00334 00335 void USB_MSD::sendCSW() { 00336 csw.Signature = CSW_Signature; 00337 _device->writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); 00338 stage = WAIT_CSW; 00339 } 00340 00341 bool USB_MSD::requestSense (void) { 00342 uint8_t request_sense[] = { 00343 0x70, 00344 0x00, 00345 0x05, // Sense Key: illegal request 00346 0x00, 00347 0x00, 00348 0x00, 00349 0x00, 00350 0x0A, 00351 0x00, 00352 0x00, 00353 0x00, 00354 0x00, 00355 0x30, 00356 0x01, 00357 0x00, 00358 0x00, 00359 0x00, 00360 0x00, 00361 }; 00362 00363 if (!write(request_sense, sizeof(request_sense))) { 00364 return false; 00365 } 00366 00367 return true; 00368 } 00369 00370 void USB_MSD::fail() { 00371 csw.Status = CSW_FAILED; 00372 sendCSW(); 00373 } 00374 00375 void USB_MSD::CBWDecode(uint8_t * buf, uint16_t size) { 00376 if (size == sizeof(cbw)) { 00377 memcpy((uint8_t *)&cbw, buf, size); 00378 if (cbw.Signature == CBW_Signature) { 00379 csw.Tag = cbw.Tag; 00380 csw.DataResidue = cbw.DataLength; 00381 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { 00382 fail(); 00383 } else { 00384 switch (cbw.CB[0]) { 00385 case TEST_UNIT_READY: 00386 testUnitReady(); 00387 break; 00388 case REQUEST_SENSE: 00389 requestSense(); 00390 break; 00391 case INQUIRY: 00392 inquiryRequest(); 00393 break; 00394 case MODE_SENSE6: 00395 modeSense6(); 00396 break; 00397 case READ_FORMAT_CAPACITIES: 00398 readFormatCapacity(); 00399 break; 00400 case READ_CAPACITY: 00401 readCapacity(); 00402 break; 00403 case READ10: 00404 case READ12: 00405 if (infoTransfer()) { 00406 if ((cbw.Flags & 0x80)) { 00407 stage = PROCESS_CBW; 00408 memoryRead(); 00409 } else { 00410 _device->stallEndpoint(EPBULK_OUT); 00411 csw.Status = CSW_ERROR; 00412 sendCSW(); 00413 } 00414 } 00415 break; 00416 case WRITE10: 00417 case WRITE12: 00418 if (infoTransfer()) { 00419 if (!(cbw.Flags & 0x80)) { 00420 stage = PROCESS_CBW; 00421 } else { 00422 _device->stallEndpoint(EPBULK_IN); 00423 csw.Status = CSW_ERROR; 00424 sendCSW(); 00425 } 00426 } 00427 break; 00428 case VERIFY10: 00429 if (!(cbw.CB[1] & 0x02)) { 00430 csw.Status = CSW_PASSED; 00431 sendCSW(); 00432 break; 00433 } 00434 if (infoTransfer()) { 00435 if (!(cbw.Flags & 0x80)) { 00436 stage = PROCESS_CBW; 00437 memOK = true; 00438 } else { 00439 _device->stallEndpoint(EPBULK_IN); 00440 csw.Status = CSW_ERROR; 00441 sendCSW(); 00442 } 00443 } 00444 break; 00445 case MEDIA_REMOVAL: 00446 csw.Status = CSW_PASSED; 00447 sendCSW(); 00448 break; 00449 default: 00450 fail(); 00451 break; 00452 } 00453 } 00454 } 00455 } 00456 } 00457 00458 void USB_MSD::testUnitReady (void) { 00459 00460 if (cbw.DataLength != 0) { 00461 if ((cbw.Flags & 0x80) != 0) { 00462 _device->stallEndpoint(EPBULK_IN); 00463 } else { 00464 _device->stallEndpoint(EPBULK_OUT); 00465 } 00466 } 00467 00468 csw.Status = CSW_PASSED; 00469 sendCSW(); 00470 } 00471 00472 void USB_MSD::memoryRead (void) { 00473 uint32_t n; 00474 00475 n = (length > MAX_PACKET) ? MAX_PACKET : length; 00476 00477 if ((addr + n) > MemorySize) { 00478 n = MemorySize - addr; 00479 stage = ERROR; 00480 } 00481 00482 // we read an entire block 00483 if (!(addr%BlockSize)) 00484 _disk->disk_read(page, addr/BlockSize); 00485 00486 // write data which are in RAM 00487 _device->writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK); 00488 00489 addr += n; 00490 length -= n; 00491 00492 csw.DataResidue -= n; 00493 00494 if ( !length || (stage != PROCESS_CBW)) { 00495 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; 00496 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; 00497 } 00498 } 00499 00500 bool USB_MSD::infoTransfer (void) { 00501 uint32_t n; 00502 00503 // Logical Block Address of First Block 00504 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); 00505 00506 addr = n * BlockSize; 00507 00508 // Number of Blocks to transfer 00509 switch (cbw.CB[0]) { 00510 case READ10: 00511 case WRITE10: 00512 case VERIFY10: 00513 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); 00514 break; 00515 00516 case READ12: 00517 case WRITE12: 00518 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); 00519 break; 00520 } 00521 00522 length = n * BlockSize; 00523 00524 if (!cbw.DataLength) { // host requests no data 00525 csw.Status = CSW_FAILED; 00526 sendCSW(); 00527 return false; 00528 } 00529 00530 if (cbw.DataLength != length) { 00531 if ((cbw.Flags & 0x80) != 0) { 00532 _device->stallEndpoint(EPBULK_IN); 00533 } else { 00534 _device->stallEndpoint(EPBULK_OUT); 00535 } 00536 00537 csw.Status = CSW_FAILED; 00538 sendCSW(); 00539 return false; 00540 } 00541 00542 return true; 00543 }
Generated on Wed Jul 13 2022 08:08:25 by 1.7.2