USB device stack - modified
Fork of USBDevice by
Embed:
(wiki syntax)
Show/hide line numbers
USBMSD.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 "USBMSD.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 { 00061 CSW_PASSED, 00062 CSW_FAILED, 00063 CSW_ERROR, 00064 }; 00065 00066 00067 USBMSD::USBMSD( uint16_t vendor_id, uint16_t product_id, uint16_t product_release ): USBDevice( vendor_id, product_id, product_release ) 00068 { 00069 } 00070 00071 00072 00073 // Called in ISR context to process a class specific request 00074 bool USBMSD::USBCallback_request( void ) 00075 { 00076 bool success = false; 00077 CONTROL_TRANSFER *transfer = getTransferPtr(); 00078 static uint8_t maxLUN[1] = {0}; 00079 00080 if ( transfer->setup.bmRequestType.Type == CLASS_TYPE ) 00081 { 00082 switch ( transfer->setup.bRequest ) 00083 { 00084 case MSC_REQUEST_RESET: 00085 reset(); 00086 success = true; 00087 break; 00088 00089 case MSC_REQUEST_GET_MAX_LUN: 00090 transfer->remaining = 1; 00091 transfer->ptr = maxLUN; 00092 transfer->direction = DEVICE_TO_HOST; 00093 success = true; 00094 break; 00095 00096 default: 00097 break; 00098 } 00099 } 00100 00101 return success; 00102 } 00103 00104 00105 bool USBMSD::connect() 00106 { 00107 //disk initialization 00108 if ( disk_status() & NO_INIT ) 00109 { 00110 if ( disk_initialize() ) 00111 { 00112 return false; 00113 } 00114 } 00115 00116 // get number of blocks 00117 BlockCount = disk_sectors(); 00118 // get memory size 00119 MemorySize = disk_size(); 00120 00121 if ( BlockCount >= 0 ) 00122 { 00123 BlockSize = MemorySize / BlockCount; 00124 00125 if ( BlockSize != 0 ) 00126 { 00127 page = ( uint8_t * )malloc( BlockSize * sizeof( uint8_t ) ); 00128 00129 if ( page == NULL ) 00130 { 00131 return false; 00132 } 00133 } 00134 } 00135 else 00136 { 00137 return false; 00138 } 00139 00140 //connect the device 00141 USBDevice::connect(); 00142 return true; 00143 } 00144 00145 00146 void USBMSD::reset() 00147 { 00148 stage = READ_CBW; 00149 } 00150 00151 00152 // Called in ISR context called when a data is received 00153 bool USBMSD::EP2_OUT_callback() 00154 { 00155 uint32_t size = 0; 00156 uint8_t buf[MAX_PACKET_SIZE_EPBULK]; 00157 readEP( EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK ); 00158 00159 switch ( stage ) 00160 { 00161 // the device has to decode the CBW received 00162 case READ_CBW: 00163 CBWDecode( buf, size ); 00164 break; 00165 00166 // the device has to receive data from the host 00167 case PROCESS_CBW: 00168 switch ( cbw.CB[0] ) 00169 { 00170 case WRITE10: 00171 case WRITE12: 00172 memoryWrite( buf, size ); 00173 break; 00174 00175 case VERIFY10: 00176 memoryVerify( buf, size ); 00177 break; 00178 } 00179 00180 break; 00181 00182 // an error has occured: stall endpoint and send CSW 00183 default: 00184 stallEndpoint( EPBULK_OUT ); 00185 csw.Status = CSW_ERROR; 00186 sendCSW(); 00187 break; 00188 } 00189 00190 //reactivate readings on the OUT bulk endpoint 00191 readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK ); 00192 return true; 00193 } 00194 00195 // Called in ISR context when a data has been transferred 00196 bool USBMSD::EP2_IN_callback() 00197 { 00198 switch ( stage ) 00199 { 00200 // the device has to send data to the host 00201 case PROCESS_CBW: 00202 switch ( cbw.CB[0] ) 00203 { 00204 case READ10: 00205 case READ12: 00206 memoryRead(); 00207 break; 00208 } 00209 00210 break; 00211 00212 //the device has to send a CSW 00213 case SEND_CSW: 00214 sendCSW(); 00215 break; 00216 00217 // an error has occured 00218 case ERROR: 00219 stallEndpoint( EPBULK_IN ); 00220 sendCSW(); 00221 break; 00222 00223 // the host has received the CSW -> we wait a CBW 00224 case WAIT_CSW: 00225 stage = READ_CBW; 00226 break; 00227 } 00228 00229 return true; 00230 } 00231 00232 00233 void USBMSD::memoryWrite ( uint8_t *buf, uint16_t size ) 00234 { 00235 if ( ( addr + size ) > MemorySize ) 00236 { 00237 size = MemorySize - addr; 00238 stage = ERROR; 00239 stallEndpoint( EPBULK_OUT ); 00240 } 00241 00242 // we fill an array in RAM of 1 block before writing it in memory 00243 for ( int i = 0; i < size; i++ ) 00244 { 00245 page[addr % BlockSize + i] = buf[i]; 00246 } 00247 00248 // if the array is filled, write it in memory 00249 if ( !( ( addr + size ) % BlockSize ) ) 00250 { 00251 if ( !( disk_status() & WRITE_PROTECT ) ) 00252 { 00253 disk_write( ( const char * )page, addr / BlockSize ); 00254 } 00255 } 00256 00257 addr += size; 00258 length -= size; 00259 csw.DataResidue -= size; 00260 00261 if ( ( !length ) || ( stage != PROCESS_CBW ) ) 00262 { 00263 csw.Status = ( stage == ERROR ) ? CSW_FAILED : CSW_PASSED; 00264 sendCSW(); 00265 } 00266 } 00267 00268 void USBMSD::memoryVerify ( uint8_t *buf, uint16_t size ) 00269 { 00270 uint32_t n; 00271 00272 if ( ( addr + size ) > MemorySize ) 00273 { 00274 size = MemorySize - addr; 00275 stage = ERROR; 00276 stallEndpoint( EPBULK_OUT ); 00277 } 00278 00279 // beginning of a new block -> load a whole block in RAM 00280 if ( !( addr % BlockSize ) ) 00281 { 00282 disk_read( ( char * )page, addr / BlockSize ); 00283 } 00284 00285 // info are in RAM -> no need to re-read memory 00286 for ( n = 0; n < size; n++ ) 00287 { 00288 if ( page[addr % BlockSize + n] != buf[n] ) 00289 { 00290 memOK = false; 00291 break; 00292 } 00293 } 00294 00295 addr += size; 00296 length -= size; 00297 csw.DataResidue -= size; 00298 00299 if ( !length || ( stage != PROCESS_CBW ) ) 00300 { 00301 csw.Status = ( memOK && ( stage == PROCESS_CBW ) ) ? CSW_PASSED : CSW_FAILED; 00302 sendCSW(); 00303 } 00304 } 00305 00306 00307 bool USBMSD::inquiryRequest ( void ) 00308 { 00309 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00310 36 - 4, 0x80, 0x00, 0x00, 00311 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00312 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00313 '1', '.', '0', ' ', 00314 }; 00315 00316 if ( !write( inquiry, sizeof( inquiry ) ) ) 00317 { 00318 return false; 00319 } 00320 00321 return true; 00322 } 00323 00324 00325 bool USBMSD::readFormatCapacity() 00326 { 00327 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00328 ( BlockCount >> 24 ) & 0xff, 00329 ( BlockCount >> 16 ) & 0xff, 00330 ( BlockCount >> 8 ) & 0xff, 00331 ( BlockCount >> 0 ) & 0xff, 00332 00333 0x02, 00334 ( BlockSize >> 16 ) & 0xff, 00335 ( BlockSize >> 8 ) & 0xff, 00336 ( BlockSize >> 0 ) & 0xff, 00337 }; 00338 00339 if ( !write( capacity, sizeof( capacity ) ) ) 00340 { 00341 return false; 00342 } 00343 00344 return true; 00345 } 00346 00347 00348 bool USBMSD::readCapacity ( void ) 00349 { 00350 uint8_t capacity[] = 00351 { 00352 ( ( BlockCount - 1 ) >> 24 ) & 0xff, 00353 ( ( BlockCount - 1 ) >> 16 ) & 0xff, 00354 ( ( BlockCount - 1 ) >> 8 ) & 0xff, 00355 ( ( BlockCount - 1 ) >> 0 ) & 0xff, 00356 00357 ( BlockSize >> 24 ) & 0xff, 00358 ( BlockSize >> 16 ) & 0xff, 00359 ( BlockSize >> 8 ) & 0xff, 00360 ( BlockSize >> 0 ) & 0xff, 00361 }; 00362 00363 if ( !write( capacity, sizeof( capacity ) ) ) 00364 { 00365 return false; 00366 } 00367 00368 return true; 00369 } 00370 00371 bool USBMSD::write ( uint8_t *buf, uint16_t size ) 00372 { 00373 if ( size >= cbw.DataLength ) 00374 { 00375 size = cbw.DataLength; 00376 } 00377 00378 stage = SEND_CSW; 00379 00380 if ( !writeNB( EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK ) ) 00381 { 00382 return false; 00383 } 00384 00385 csw.DataResidue -= size; 00386 csw.Status = CSW_PASSED; 00387 return true; 00388 } 00389 00390 00391 bool USBMSD::modeSense6 ( void ) 00392 { 00393 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00394 00395 if ( !write( sense6, sizeof( sense6 ) ) ) 00396 { 00397 return false; 00398 } 00399 00400 return true; 00401 } 00402 00403 void USBMSD::sendCSW() 00404 { 00405 csw.Signature = CSW_Signature; 00406 writeNB( EPBULK_IN, ( uint8_t * )&csw, sizeof( CSW ), MAX_PACKET_SIZE_EPBULK ); 00407 stage = WAIT_CSW; 00408 } 00409 00410 bool USBMSD::requestSense ( void ) 00411 { 00412 uint8_t request_sense[] = 00413 { 00414 0x70, 00415 0x00, 00416 0x05, // Sense Key: illegal request 00417 0x00, 00418 0x00, 00419 0x00, 00420 0x00, 00421 0x0A, 00422 0x00, 00423 0x00, 00424 0x00, 00425 0x00, 00426 0x30, 00427 0x01, 00428 0x00, 00429 0x00, 00430 0x00, 00431 0x00, 00432 }; 00433 00434 if ( !write( request_sense, sizeof( request_sense ) ) ) 00435 { 00436 return false; 00437 } 00438 00439 return true; 00440 } 00441 00442 void USBMSD::fail() 00443 { 00444 csw.Status = CSW_FAILED; 00445 sendCSW(); 00446 } 00447 00448 00449 void USBMSD::CBWDecode( uint8_t *buf, uint16_t size ) 00450 { 00451 if ( size == sizeof( cbw ) ) 00452 { 00453 memcpy( ( uint8_t * )&cbw, buf, size ); 00454 00455 if ( cbw.Signature == CBW_Signature ) 00456 { 00457 csw.Tag = cbw.Tag; 00458 csw.DataResidue = cbw.DataLength; 00459 00460 if ( ( cbw.CBLength < 1 ) || ( cbw.CBLength > 16 ) ) 00461 { 00462 fail(); 00463 } 00464 else 00465 { 00466 switch ( cbw.CB[0] ) 00467 { 00468 case TEST_UNIT_READY: 00469 testUnitReady(); 00470 break; 00471 00472 case REQUEST_SENSE: 00473 requestSense(); 00474 break; 00475 00476 case INQUIRY: 00477 inquiryRequest(); 00478 break; 00479 00480 case MODE_SENSE6: 00481 modeSense6(); 00482 break; 00483 00484 case READ_FORMAT_CAPACITIES: 00485 readFormatCapacity(); 00486 break; 00487 00488 case READ_CAPACITY: 00489 readCapacity(); 00490 break; 00491 00492 case READ10: 00493 case READ12: 00494 if ( infoTransfer() ) 00495 { 00496 if ( ( cbw.Flags & 0x80 ) ) 00497 { 00498 stage = PROCESS_CBW; 00499 memoryRead(); 00500 } 00501 else 00502 { 00503 stallEndpoint( EPBULK_OUT ); 00504 csw.Status = CSW_ERROR; 00505 sendCSW(); 00506 } 00507 } 00508 00509 break; 00510 00511 case WRITE10: 00512 case WRITE12: 00513 if ( infoTransfer() ) 00514 { 00515 if ( !( cbw.Flags & 0x80 ) ) 00516 { 00517 stage = PROCESS_CBW; 00518 } 00519 else 00520 { 00521 stallEndpoint( EPBULK_IN ); 00522 csw.Status = CSW_ERROR; 00523 sendCSW(); 00524 } 00525 } 00526 00527 break; 00528 00529 case VERIFY10: 00530 if ( !( cbw.CB[1] & 0x02 ) ) 00531 { 00532 csw.Status = CSW_PASSED; 00533 sendCSW(); 00534 break; 00535 } 00536 00537 if ( infoTransfer() ) 00538 { 00539 if ( !( cbw.Flags & 0x80 ) ) 00540 { 00541 stage = PROCESS_CBW; 00542 memOK = true; 00543 } 00544 else 00545 { 00546 stallEndpoint( EPBULK_IN ); 00547 csw.Status = CSW_ERROR; 00548 sendCSW(); 00549 } 00550 } 00551 00552 break; 00553 00554 default: 00555 fail(); 00556 break; 00557 } 00558 } 00559 } 00560 } 00561 } 00562 00563 void USBMSD::testUnitReady ( void ) 00564 { 00565 if ( cbw.DataLength != 0 ) 00566 { 00567 if ( ( cbw.Flags & 0x80 ) != 0 ) 00568 { 00569 stallEndpoint( EPBULK_IN ); 00570 } 00571 else 00572 { 00573 stallEndpoint( EPBULK_OUT ); 00574 } 00575 } 00576 00577 csw.Status = CSW_PASSED; 00578 sendCSW(); 00579 } 00580 00581 00582 void USBMSD::memoryRead ( void ) 00583 { 00584 uint32_t n; 00585 n = ( length > MAX_PACKET ) ? MAX_PACKET : length; 00586 00587 if ( ( addr + n ) > MemorySize ) 00588 { 00589 n = MemorySize - addr; 00590 stage = ERROR; 00591 } 00592 00593 // we read an entire block 00594 if ( !( addr % BlockSize ) ) 00595 { 00596 disk_read( ( char * )page, addr / BlockSize ); 00597 } 00598 00599 // write data which are in RAM 00600 writeNB( EPBULK_IN, &page[addr % BlockSize], n, MAX_PACKET_SIZE_EPBULK ); 00601 addr += n; 00602 length -= n; 00603 csw.DataResidue -= n; 00604 00605 if ( !length || ( stage != PROCESS_CBW ) ) 00606 { 00607 csw.Status = ( stage == PROCESS_CBW ) ? CSW_PASSED : CSW_FAILED; 00608 stage = ( stage == PROCESS_CBW ) ? SEND_CSW : stage; 00609 } 00610 } 00611 00612 00613 bool USBMSD::infoTransfer ( void ) 00614 { 00615 uint32_t n; 00616 // Logical Block Address of First Block 00617 n = ( cbw.CB[2] << 24 ) | ( cbw.CB[3] << 16 ) | ( cbw.CB[4] << 8 ) | ( cbw.CB[5] << 0 ); 00618 addr = n * BlockSize; 00619 00620 // Number of Blocks to transfer 00621 switch ( cbw.CB[0] ) 00622 { 00623 case READ10: 00624 case WRITE10: 00625 case VERIFY10: 00626 n = ( cbw.CB[7] << 8 ) | ( cbw.CB[8] << 0 ); 00627 break; 00628 00629 case READ12: 00630 case WRITE12: 00631 n = ( cbw.CB[6] << 24 ) | ( cbw.CB[7] << 16 ) | ( cbw.CB[8] << 8 ) | ( cbw.CB[9] << 0 ); 00632 break; 00633 } 00634 00635 length = n * BlockSize; 00636 00637 if ( !cbw.DataLength ) // host requests no data 00638 { 00639 csw.Status = CSW_FAILED; 00640 sendCSW(); 00641 return false; 00642 } 00643 00644 if ( cbw.DataLength != length ) 00645 { 00646 if ( ( cbw.Flags & 0x80 ) != 0 ) 00647 { 00648 stallEndpoint( EPBULK_IN ); 00649 } 00650 else 00651 { 00652 stallEndpoint( EPBULK_OUT ); 00653 } 00654 00655 csw.Status = CSW_FAILED; 00656 sendCSW(); 00657 return false; 00658 } 00659 00660 return true; 00661 } 00662 00663 00664 00665 00666 00667 // Called in ISR context 00668 // Set configuration. Return false if the 00669 // configuration is not supported. 00670 bool USBMSD::USBCallback_setConfiguration( uint8_t configuration ) 00671 { 00672 if ( configuration != DEFAULT_CONFIGURATION ) 00673 { 00674 return false; 00675 } 00676 00677 // Configure endpoints > 0 00678 addEndpoint( EPBULK_IN, MAX_PACKET_SIZE_EPBULK ); 00679 addEndpoint( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK ); 00680 //activate readings 00681 readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK ); 00682 return true; 00683 } 00684 00685 00686 uint8_t *USBMSD::stringIinterfaceDesc() 00687 { 00688 static uint8_t stringIinterfaceDescriptor[] = 00689 { 00690 0x08, //bLength 00691 STRING_DESCRIPTOR, //bDescriptorType 0x03 00692 'M', 0, 'S', 0, 'D', 0 //bString iInterface - MSD 00693 }; 00694 return stringIinterfaceDescriptor; 00695 } 00696 00697 uint8_t *USBMSD::stringIproductDesc() 00698 { 00699 static uint8_t stringIproductDescriptor[] = 00700 { 00701 0x12, //bLength 00702 STRING_DESCRIPTOR, //bDescriptorType 0x03 00703 'M', 0, 'b', 0, 'e', 0, 'd', 0, ' ', 0, 'M', 0, 'S', 0, 'D', 0 //bString iProduct - Mbed Audio 00704 }; 00705 return stringIproductDescriptor; 00706 } 00707 00708 00709 uint8_t *USBMSD::configurationDesc() 00710 { 00711 static uint8_t configDescriptor[] = 00712 { 00713 00714 // Configuration 1 00715 9, // bLength 00716 2, // bDescriptorType 00717 LSB( 9 + 9 + 7 + 7 ), // wTotalLength 00718 MSB( 9 + 9 + 7 + 7 ), 00719 0x01, // bNumInterfaces 00720 0x01, // bConfigurationValue: 0x01 is used to select this configuration 00721 0x00, // iConfiguration: no string to describe this configuration 00722 0xC0, // bmAttributes 00723 100, // bMaxPower, device power consumption is 100 mA 00724 00725 // Interface 0, Alternate Setting 0, MSC Class 00726 9, // bLength 00727 4, // bDescriptorType 00728 0x00, // bInterfaceNumber 00729 0x00, // bAlternateSetting 00730 0x02, // bNumEndpoints 00731 0x08, // bInterfaceClass 00732 0x06, // bInterfaceSubClass 00733 0x50, // bInterfaceProtocol 00734 0x04, // iInterface 00735 00736 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00737 7, // bLength 00738 5, // bDescriptorType 00739 PHY_TO_DESC( EPBULK_IN ), // bEndpointAddress 00740 0x02, // bmAttributes (0x02=bulk) 00741 LSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (LSB) 00742 MSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (MSB) 00743 0, // bInterval 00744 00745 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00746 7, // bLength 00747 5, // bDescriptorType 00748 PHY_TO_DESC( EPBULK_OUT ), // bEndpointAddress 00749 0x02, // bmAttributes (0x02=bulk) 00750 LSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (LSB) 00751 MSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (MSB) 00752 0 // bInterval 00753 }; 00754 return configDescriptor; 00755 } 00756
Generated on Sat Jul 16 2022 03:17:41 by 1.7.2