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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
USBMSD.cpp
00001 /* 00002 * Copyright (c) 2018-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include <stdint.h> 00019 #include <stdlib.h> 00020 #include "USBMSD.h" 00021 #include "EndpointResolver.h" 00022 #include "usb_phy_api.h" 00023 00024 #define DISK_OK 0x00 00025 #define NO_INIT 0x01 00026 #define NO_DISK 0x02 00027 #define WRITE_PROTECT 0x04 00028 00029 #define CBW_Signature 0x43425355 00030 #define CSW_Signature 0x53425355 00031 00032 // SCSI Commands 00033 #define TEST_UNIT_READY 0x00 00034 #define REQUEST_SENSE 0x03 00035 #define FORMAT_UNIT 0x04 00036 #define INQUIRY 0x12 00037 #define MODE_SELECT6 0x15 00038 #define MODE_SENSE6 0x1A 00039 #define START_STOP_UNIT 0x1B 00040 #define MEDIA_REMOVAL 0x1E 00041 #define READ_FORMAT_CAPACITIES 0x23 00042 #define READ_CAPACITY 0x25 00043 #define READ10 0x28 00044 #define WRITE10 0x2A 00045 #define VERIFY10 0x2F 00046 #define READ12 0xA8 00047 #define WRITE12 0xAA 00048 #define MODE_SELECT10 0x55 00049 #define MODE_SENSE10 0x5A 00050 00051 // MSC class specific requests 00052 #define MSC_REQUEST_RESET 0xFF 00053 #define MSC_REQUEST_GET_MAX_LUN 0xFE 00054 00055 #define DEFAULT_CONFIGURATION (1) 00056 00057 // max packet size 00058 #define MAX_PACKET 64 00059 00060 // CSW Status 00061 enum Status { 00062 CSW_PASSED, 00063 CSW_FAILED, 00064 CSW_ERROR, 00065 }; 00066 00067 USBMSD::USBMSD(BlockDevice *bd, bool connect_blocking, uint16_t vendor_id, uint16_t product_id, uint16_t product_release) 00068 : USBDevice(get_usb_phy(), vendor_id, product_id, product_release), 00069 _initialized(false), _media_removed(false), _in_task(&_queue), _out_task(&_queue), _reset_task(&_queue), _control_task(&_queue), _configure_task(&_queue), _bd(bd), 00070 _addr(0), _length(0), _mem_ok(false), _block_size(0), _memory_size(0), _block_count(0), _out_ready(false), _in_ready(false), _bulk_out_size(0) 00071 { 00072 _init(); 00073 if (connect_blocking) { 00074 connect(); 00075 } else { 00076 init(); 00077 } 00078 } 00079 00080 USBMSD::USBMSD(USBPhy *phy, BlockDevice *bd, uint16_t vendor_id, uint16_t product_id, uint16_t product_release) 00081 : USBDevice(phy, vendor_id, product_id, product_release), 00082 _initialized(false), _media_removed(false), _in_task(&_queue), _out_task(&_queue), _reset_task(&_queue), _control_task(&_queue), _configure_task(&_queue), _bd(bd), 00083 _addr(0), _length(0), _mem_ok(false), _block_size(0), _memory_size(0), _block_count(0), _out_ready(false), _in_ready(false), _bulk_out_size(0) 00084 { 00085 _init(); 00086 } 00087 00088 00089 void USBMSD::_init() 00090 { 00091 _bd->init(); 00092 00093 _in_task = mbed::callback(this, &USBMSD::_in); 00094 _out_task = mbed::callback(this, &USBMSD::_out); 00095 _reset_task = mbed::callback(this, &USBMSD::_reset); 00096 _control_task = mbed::callback(this, &USBMSD::_control); 00097 _configure_task = mbed::callback(this, &USBMSD::_configure); 00098 00099 EndpointResolver resolver(endpoint_table()); 00100 00101 resolver.endpoint_ctrl(64); 00102 _bulk_in = resolver.endpoint_in(USB_EP_TYPE_BULK, MAX_PACKET); 00103 _bulk_out = resolver.endpoint_out(USB_EP_TYPE_BULK, MAX_PACKET); 00104 MBED_ASSERT(resolver.valid()); 00105 00106 _stage = READ_CBW; 00107 memset((void *)&_cbw, 0, sizeof(CBW)); 00108 memset((void *)&_csw, 0, sizeof(CSW)); 00109 _page = NULL; 00110 } 00111 00112 USBMSD::~USBMSD() 00113 { 00114 disconnect(); 00115 _bd->deinit(); 00116 deinit(); 00117 } 00118 00119 bool USBMSD::connect() 00120 { 00121 _mutex_init.lock(); 00122 _mutex.lock(); 00123 00124 // already initialized 00125 if (_initialized) { 00126 _mutex.unlock(); 00127 _mutex_init.unlock(); 00128 return false; 00129 } 00130 00131 //disk initialization 00132 if (disk_status() & NO_INIT) { 00133 if (disk_initialize()) { 00134 _mutex.unlock(); 00135 _mutex_init.unlock(); 00136 return false; 00137 } 00138 } 00139 00140 // get number of blocks 00141 _block_count = disk_sectors(); 00142 00143 // get memory size 00144 _memory_size = disk_size(); 00145 00146 if (_block_count > 0) { 00147 _block_size = _memory_size / _block_count; 00148 if (_block_size != 0) { 00149 free(_page); 00150 _page = (uint8_t *)malloc(_block_size * sizeof(uint8_t)); 00151 if (_page == NULL) { 00152 _mutex.unlock(); 00153 _mutex_init.unlock(); 00154 return false; 00155 } 00156 } 00157 } else { 00158 _mutex.unlock(); 00159 _mutex_init.unlock(); 00160 return false; 00161 } 00162 00163 //connect the device 00164 USBDevice::connect(); 00165 _initialized = true; 00166 _media_removed = false; 00167 _mutex.unlock(); 00168 _mutex_init.unlock(); 00169 return true; 00170 } 00171 00172 void USBMSD::disconnect() 00173 { 00174 _mutex_init.lock(); 00175 _mutex.lock(); 00176 00177 USBDevice::disconnect(); 00178 _initialized = false; 00179 00180 _in_task.cancel(); 00181 _out_task.cancel(); 00182 _reset_task.cancel(); 00183 _control_task.cancel(); 00184 _configure_task.cancel(); 00185 00186 _mutex.unlock(); 00187 00188 // object mutex must be unlocked for waiting 00189 _in_task.wait(); 00190 _out_task.wait(); 00191 _reset_task.wait(); 00192 _control_task.wait(); 00193 _configure_task.wait(); 00194 00195 _mutex.lock(); 00196 00197 //De-allocate MSD page size: 00198 free(_page); 00199 _page = NULL; 00200 00201 _mutex.unlock(); 00202 _mutex_init.unlock(); 00203 } 00204 00205 void USBMSD::process() 00206 { 00207 _queue.dispatch(); 00208 } 00209 00210 void USBMSD::attach(mbed::Callback<void()> cb) 00211 { 00212 lock(); 00213 00214 _queue.attach(cb); 00215 00216 unlock(); 00217 } 00218 00219 bool USBMSD::media_removed() 00220 { 00221 return _media_removed; 00222 } 00223 00224 int USBMSD::disk_read(uint8_t *data, uint64_t block, uint8_t count) 00225 { 00226 bd_addr_t addr = block * _bd->get_erase_size(); 00227 bd_size_t size = count * _bd->get_erase_size(); 00228 return _bd->read(data, addr, size); 00229 } 00230 00231 int USBMSD::disk_write(const uint8_t *data, uint64_t block, uint8_t count) 00232 { 00233 bd_addr_t addr = block * _bd->get_erase_size(); 00234 bd_size_t size = count * _bd->get_erase_size(); 00235 int ret = _bd->erase(addr, size); 00236 if (ret != 0) { 00237 return ret; 00238 } 00239 00240 return _bd->program(data, addr, size); 00241 } 00242 00243 int USBMSD::disk_initialize() 00244 { 00245 return 0; 00246 } 00247 00248 uint64_t USBMSD::disk_sectors() 00249 { 00250 return _bd->size() / _bd->get_erase_size(); 00251 } 00252 00253 uint64_t USBMSD::disk_size() 00254 { 00255 return _bd->size(); 00256 } 00257 00258 00259 int USBMSD::disk_status() 00260 { 00261 return 0; 00262 } 00263 00264 void USBMSD::_isr_out() 00265 { 00266 _out_task.call(); 00267 } 00268 00269 void USBMSD::_isr_in() 00270 { 00271 _in_task.call(); 00272 } 00273 00274 void USBMSD::callback_state_change(DeviceState new_state) 00275 { 00276 // called in ISR context 00277 00278 if (new_state != Configured) { 00279 _reset_task.cancel(); 00280 _reset_task.call(); 00281 } 00282 } 00283 00284 void USBMSD::callback_request(const setup_packet_t *setup) 00285 { 00286 // called in ISR context 00287 00288 if (setup->bmRequestType.Type == CLASS_TYPE) { 00289 _control_task.call(setup); 00290 } else { 00291 complete_request(PassThrough, NULL, 0); 00292 } 00293 } 00294 00295 void USBMSD::callback_request_xfer_done(const setup_packet_t *setup, bool aborted) 00296 { 00297 // called in ISR context 00298 00299 bool success = setup->bRequest == MSC_REQUEST_GET_MAX_LUN; 00300 complete_request_xfer_done(success); 00301 } 00302 00303 void USBMSD::callback_set_configuration(uint8_t configuration) 00304 { 00305 // called in ISR context 00306 00307 if (configuration != DEFAULT_CONFIGURATION) { 00308 complete_set_configuration(false); 00309 return; 00310 } 00311 _configure_task.call(); 00312 } 00313 00314 void USBMSD::callback_set_interface(uint16_t interface, uint8_t alternate) 00315 { 00316 // called in ISR context 00317 00318 bool success = (interface == 0) && (alternate == 0); 00319 complete_set_interface(success); 00320 } 00321 00322 00323 const uint8_t *USBMSD::string_iinterface_desc() 00324 { 00325 static const uint8_t string_iinterface_descriptor[] = { 00326 0x08, //bLength 00327 STRING_DESCRIPTOR, //bDescriptorType 0x03 00328 'M', 0, 'S', 0, 'D', 0 //bString iInterface - MSD 00329 }; 00330 return string_iinterface_descriptor; 00331 } 00332 00333 const uint8_t *USBMSD::string_iproduct_desc() 00334 { 00335 static const uint8_t string_iproduct_descriptor[] = { 00336 0x12, //bLength 00337 STRING_DESCRIPTOR, //bDescriptorType 0x03 00338 'M', 0, 'b', 0, 'e', 0, 'd', 0, ' ', 0, 'M', 0, 'S', 0, 'D', 0 //bString iProduct - Mbed Audio 00339 }; 00340 return string_iproduct_descriptor; 00341 } 00342 00343 00344 const uint8_t *USBMSD::configuration_desc(uint8_t index) 00345 { 00346 if (index != 0) { 00347 return NULL; 00348 } 00349 00350 uint8_t config_descriptor_temp[] = { 00351 00352 // Configuration 1 00353 9, // bLength 00354 2, // bDescriptorType 00355 LSB(9 + 9 + 7 + 7), // wTotalLength 00356 MSB(9 + 9 + 7 + 7), 00357 0x01, // bNumInterfaces 00358 0x01, // bConfigurationValue: 0x01 is used to select this configuration 00359 0x00, // iConfiguration: no string to describe this configuration 00360 0xC0, // bmAttributes 00361 100, // bMaxPower, device power consumption is 100 mA 00362 00363 // Interface 0, Alternate Setting 0, MSC Class 00364 9, // bLength 00365 4, // bDescriptorType 00366 0x00, // bInterfaceNumber 00367 0x00, // bAlternateSetting 00368 0x02, // bNumEndpoints 00369 0x08, // bInterfaceClass 00370 0x06, // bInterfaceSubClass 00371 0x50, // bInterfaceProtocol 00372 0x04, // iInterface 00373 00374 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00375 7, // bLength 00376 5, // bDescriptorType 00377 _bulk_in, // bEndpointAddress 00378 0x02, // bmAttributes (0x02=bulk) 00379 LSB(MAX_PACKET), // wMaxPacketSize (LSB) 00380 MSB(MAX_PACKET), // wMaxPacketSize (MSB) 00381 0, // bInterval 00382 00383 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00384 7, // bLength 00385 5, // bDescriptorType 00386 _bulk_out, // bEndpointAddress 00387 0x02, // bmAttributes (0x02=bulk) 00388 LSB(MAX_PACKET), // wMaxPacketSize (LSB) 00389 MSB(MAX_PACKET), // wMaxPacketSize (MSB) 00390 0 // bInterval 00391 }; 00392 MBED_ASSERT(sizeof(config_descriptor_temp) == sizeof(_configuration_descriptor)); 00393 memcpy(_configuration_descriptor, config_descriptor_temp, sizeof(_configuration_descriptor)); 00394 return _configuration_descriptor; 00395 } 00396 00397 void USBMSD::_out() 00398 { 00399 _mutex.lock(); 00400 00401 _bulk_out_size = read_finish(_bulk_out); 00402 _out_ready = true; 00403 _process(); 00404 00405 _mutex.unlock(); 00406 } 00407 00408 void USBMSD::_in() 00409 { 00410 _mutex.lock(); 00411 00412 write_finish(_bulk_in); 00413 _in_ready = true; 00414 _process(); 00415 00416 _mutex.unlock(); 00417 } 00418 00419 void USBMSD::_reset() 00420 { 00421 _mutex.lock(); 00422 00423 msd_reset(); 00424 00425 _mutex.unlock(); 00426 } 00427 00428 void USBMSD::_control(const setup_packet_t *setup) 00429 { 00430 _mutex.lock(); 00431 00432 static const uint8_t maxLUN[1] = {0}; 00433 00434 RequestResult result = PassThrough; 00435 uint8_t *data = NULL; 00436 uint32_t size = 0; 00437 00438 if (setup->bmRequestType.Type == CLASS_TYPE) { 00439 switch (setup->bRequest) { 00440 case MSC_REQUEST_RESET: 00441 result = Success; 00442 msd_reset(); 00443 break; 00444 case MSC_REQUEST_GET_MAX_LUN: 00445 result = Send; 00446 data = (uint8_t *)maxLUN; 00447 size = 1; 00448 break; 00449 default: 00450 break; 00451 } 00452 } 00453 00454 complete_request(result, data, size); 00455 00456 _mutex.unlock(); 00457 } 00458 00459 void USBMSD::_configure() 00460 { 00461 _mutex.lock(); 00462 00463 // Configure endpoints > 0 00464 endpoint_add(_bulk_in, MAX_PACKET, USB_EP_TYPE_BULK, &USBMSD::_isr_in); 00465 endpoint_add(_bulk_out, MAX_PACKET, USB_EP_TYPE_BULK, &USBMSD::_isr_out); 00466 MBED_ASSERT(sizeof(_bulk_out_buf) == MAX_PACKET); 00467 MBED_ASSERT(sizeof(_bulk_in_buf) == MAX_PACKET); 00468 00469 _out_ready = false; 00470 _in_ready = true; 00471 00472 //activate readings 00473 read_start(_bulk_out, _bulk_out_buf, sizeof(_bulk_out_buf)); 00474 complete_set_configuration(true); 00475 00476 _mutex.unlock(); 00477 } 00478 00479 void USBMSD::_process() 00480 { 00481 // Mutex must be locked by caller 00482 00483 switch (_stage) { 00484 // the device has to decode the CBW received 00485 case READ_CBW: 00486 if (!_out_ready) { 00487 break; 00488 } 00489 CBWDecode(_bulk_out_buf, _bulk_out_size); 00490 _read_next(); 00491 break; 00492 00493 00494 case PROCESS_CBW: 00495 switch (_cbw.CB[0]) { 00496 // the device has to receive data from the host 00497 case WRITE10: 00498 case WRITE12: 00499 if (!_out_ready) { 00500 break; 00501 } 00502 memoryWrite(_bulk_out_buf, _bulk_out_size); 00503 _read_next(); 00504 break; 00505 case VERIFY10: 00506 if (!_out_ready) { 00507 break; 00508 } 00509 memoryVerify(_bulk_out_buf, _bulk_out_size); 00510 _read_next(); 00511 break; 00512 // the device has to send data to the host 00513 case READ10: 00514 case READ12: 00515 if (!_in_ready) { 00516 break; 00517 } 00518 memoryRead(); 00519 break; 00520 } 00521 break; 00522 00523 //the device has to send a CSW 00524 case SEND_CSW: 00525 if (!_in_ready) { 00526 break; 00527 } 00528 sendCSW(); 00529 break; 00530 00531 // an error has occurred: stall endpoint and send CSW 00532 default: 00533 endpoint_stall(_bulk_out); 00534 endpoint_stall(_bulk_in); 00535 _csw.Status = CSW_ERROR; 00536 sendCSW(); 00537 break; 00538 } 00539 } 00540 00541 void USBMSD::_write_next(uint8_t *data, uint32_t size) 00542 { 00543 lock(); 00544 00545 MBED_ASSERT(size <= MAX_PACKET); 00546 MBED_ASSERT(_in_ready); 00547 uint32_t send_size = MAX_PACKET > size ? size : MAX_PACKET; 00548 memcpy(_bulk_in_buf, data, send_size); 00549 write_start(_bulk_in, _bulk_in_buf, send_size); 00550 _in_ready = false; 00551 00552 unlock(); 00553 } 00554 00555 void USBMSD::_read_next() 00556 { 00557 lock(); 00558 00559 MBED_ASSERT(_out_ready); 00560 read_start(_bulk_out, _bulk_out_buf, sizeof(_bulk_out_buf)); 00561 _out_ready = false; 00562 00563 unlock(); 00564 } 00565 00566 void USBMSD::memoryWrite(uint8_t *buf, uint16_t size) 00567 { 00568 if ((_addr + size) > _memory_size) { 00569 size = _memory_size - _addr; 00570 _stage = ERROR; 00571 endpoint_stall(_bulk_out); 00572 } 00573 00574 // we fill an array in RAM of 1 block before writing it in memory 00575 for (int i = 0; i < size; i++) { 00576 _page[_addr % _block_size + i] = buf[i]; 00577 } 00578 00579 // if the array is filled, write it in memory 00580 if (!((_addr + size) % _block_size)) { 00581 if (!(disk_status() & WRITE_PROTECT)) { 00582 disk_write(_page, _addr / _block_size, 1); 00583 } 00584 } 00585 00586 _addr += size; 00587 _length -= size; 00588 _csw.DataResidue -= size; 00589 00590 if ((!_length) || (_stage != PROCESS_CBW)) { 00591 _csw.Status = (_stage == ERROR) ? CSW_FAILED : CSW_PASSED; 00592 sendCSW(); 00593 } 00594 } 00595 00596 void USBMSD::memoryVerify(uint8_t *buf, uint16_t size) 00597 { 00598 uint32_t n; 00599 00600 if ((_addr + size) > _memory_size) { 00601 size = _memory_size - _addr; 00602 _stage = ERROR; 00603 endpoint_stall(_bulk_out); 00604 } 00605 00606 // beginning of a new block -> load a whole block in RAM 00607 if (!(_addr % _block_size)) { 00608 disk_read(_page, _addr / _block_size, 1); 00609 } 00610 00611 // info are in RAM -> no need to re-read memory 00612 for (n = 0; n < size; n++) { 00613 if (_page[_addr % _block_size + n] != buf[n]) { 00614 _mem_ok = false; 00615 break; 00616 } 00617 } 00618 00619 _addr += size; 00620 _length -= size; 00621 _csw.DataResidue -= size; 00622 00623 if (!_length || (_stage != PROCESS_CBW)) { 00624 _csw.Status = (_mem_ok && (_stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; 00625 sendCSW(); 00626 } 00627 } 00628 00629 00630 bool USBMSD::inquiryRequest(void) 00631 { 00632 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00633 36 - 4, 0x80, 0x00, 0x00, 00634 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00635 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00636 '1', '.', '0', ' ', 00637 }; 00638 if (!write(inquiry, sizeof(inquiry))) { 00639 return false; 00640 } 00641 return true; 00642 } 00643 00644 00645 bool USBMSD::readFormatCapacity() 00646 { 00647 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00648 (uint8_t)((_block_count >> 24) & 0xff), 00649 (uint8_t)((_block_count >> 16) & 0xff), 00650 (uint8_t)((_block_count >> 8) & 0xff), 00651 (uint8_t)((_block_count >> 0) & 0xff), 00652 00653 0x02, 00654 (uint8_t)((_block_size >> 16) & 0xff), 00655 (uint8_t)((_block_size >> 8) & 0xff), 00656 (uint8_t)((_block_size >> 0) & 0xff), 00657 }; 00658 if (!write(capacity, sizeof(capacity))) { 00659 return false; 00660 } 00661 return true; 00662 } 00663 00664 00665 bool USBMSD::readCapacity(void) 00666 { 00667 uint8_t capacity[] = { 00668 (uint8_t)(((_block_count - 1) >> 24) & 0xff), 00669 (uint8_t)(((_block_count - 1) >> 16) & 0xff), 00670 (uint8_t)(((_block_count - 1) >> 8) & 0xff), 00671 (uint8_t)(((_block_count - 1) >> 0) & 0xff), 00672 00673 (uint8_t)((_block_size >> 24) & 0xff), 00674 (uint8_t)((_block_size >> 16) & 0xff), 00675 (uint8_t)((_block_size >> 8) & 0xff), 00676 (uint8_t)((_block_size >> 0) & 0xff), 00677 }; 00678 if (!write(capacity, sizeof(capacity))) { 00679 return false; 00680 } 00681 return true; 00682 } 00683 00684 bool USBMSD::write(uint8_t *buf, uint16_t size) 00685 { 00686 00687 if (size >= _cbw.DataLength) { 00688 size = _cbw.DataLength; 00689 } 00690 _stage = SEND_CSW; 00691 00692 _write_next(buf, size); 00693 00694 _csw.DataResidue -= size; 00695 _csw.Status = CSW_PASSED; 00696 return true; 00697 } 00698 00699 00700 bool USBMSD::modeSense6(void) 00701 { 00702 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00703 if (!write(sense6, sizeof(sense6))) { 00704 return false; 00705 } 00706 return true; 00707 } 00708 00709 bool USBMSD::modeSense10(void) 00710 { 00711 uint8_t sense10[] = { 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 00712 if (!write(sense10, sizeof(sense10))) { 00713 return false; 00714 } 00715 return true; 00716 } 00717 00718 void USBMSD::sendCSW() 00719 { 00720 _csw.Signature = CSW_Signature; 00721 _write_next((uint8_t *)&_csw, sizeof(CSW)); 00722 _stage = READ_CBW; 00723 } 00724 00725 bool USBMSD::requestSense(void) 00726 { 00727 uint8_t request_sense[] = { 00728 0x70, 00729 0x00, 00730 0x05, // Sense Key: illegal request 00731 0x00, 00732 0x00, 00733 0x00, 00734 0x00, 00735 0x0A, 00736 0x00, 00737 0x00, 00738 0x00, 00739 0x00, 00740 0x30, 00741 0x01, 00742 0x00, 00743 0x00, 00744 0x00, 00745 0x00, 00746 }; 00747 00748 if (!write(request_sense, sizeof(request_sense))) { 00749 return false; 00750 } 00751 00752 return true; 00753 } 00754 00755 void USBMSD::fail() 00756 { 00757 _csw.Status = CSW_FAILED; 00758 sendCSW(); 00759 } 00760 00761 00762 void USBMSD::CBWDecode(uint8_t *buf, uint16_t size) 00763 { 00764 if (size == sizeof(_cbw)) { 00765 memcpy((uint8_t *)&_cbw, buf, size); 00766 if (_cbw.Signature == CBW_Signature) { 00767 _csw.Tag = _cbw.Tag; 00768 _csw.DataResidue = _cbw.DataLength; 00769 if ((_cbw.CBLength < 1) || (_cbw.CBLength > 16)) { 00770 fail(); 00771 } else { 00772 switch (_cbw.CB[0]) { 00773 case TEST_UNIT_READY: 00774 testUnitReady(); 00775 break; 00776 case REQUEST_SENSE: 00777 requestSense(); 00778 break; 00779 case INQUIRY: 00780 inquiryRequest(); 00781 break; 00782 case MODE_SENSE6: 00783 modeSense6(); 00784 break; 00785 case READ_FORMAT_CAPACITIES: 00786 readFormatCapacity(); 00787 break; 00788 case READ_CAPACITY: 00789 readCapacity(); 00790 break; 00791 case READ10: 00792 case READ12: 00793 if (infoTransfer()) { 00794 if ((_cbw.Flags & 0x80)) { 00795 _stage = PROCESS_CBW; 00796 memoryRead(); 00797 } else { 00798 endpoint_stall(_bulk_out); 00799 _csw.Status = CSW_ERROR; 00800 sendCSW(); 00801 } 00802 } 00803 break; 00804 case WRITE10: 00805 case WRITE12: 00806 if (infoTransfer()) { 00807 if (!(_cbw.Flags & 0x80)) { 00808 _stage = PROCESS_CBW; 00809 } else { 00810 endpoint_stall(_bulk_in); 00811 _csw.Status = CSW_ERROR; 00812 sendCSW(); 00813 } 00814 } 00815 break; 00816 case VERIFY10: 00817 if (!(_cbw.CB[1] & 0x02)) { 00818 _csw.Status = CSW_PASSED; 00819 sendCSW(); 00820 break; 00821 } 00822 if (infoTransfer()) { 00823 if (!(_cbw.Flags & 0x80)) { 00824 _stage = PROCESS_CBW; 00825 _mem_ok = true; 00826 } else { 00827 endpoint_stall(_bulk_in); 00828 _csw.Status = CSW_ERROR; 00829 sendCSW(); 00830 } 00831 } 00832 break; 00833 case MEDIA_REMOVAL: 00834 _csw.Status = CSW_PASSED; 00835 sendCSW(); 00836 _media_removed = true; 00837 break; 00838 case MODE_SENSE10: 00839 modeSense10(); 00840 break; 00841 default: 00842 fail(); 00843 break; 00844 } 00845 } 00846 } 00847 } 00848 } 00849 00850 void USBMSD::testUnitReady(void) 00851 { 00852 00853 if (_cbw.DataLength != 0) { 00854 if ((_cbw.Flags & 0x80) != 0) { 00855 endpoint_stall(_bulk_in); 00856 } else { 00857 endpoint_stall(_bulk_out); 00858 } 00859 } 00860 00861 _csw.Status = CSW_PASSED; 00862 sendCSW(); 00863 } 00864 00865 00866 void USBMSD::memoryRead(void) 00867 { 00868 uint32_t n; 00869 00870 n = (_length > MAX_PACKET) ? MAX_PACKET : _length; 00871 00872 if ((_addr + n) > _memory_size) { 00873 n = _memory_size - _addr; 00874 _stage = ERROR; 00875 } 00876 00877 // we read an entire block 00878 if (!(_addr % _block_size)) { 00879 disk_read(_page, _addr / _block_size, 1); 00880 } 00881 00882 // write data which are in RAM 00883 _write_next(&_page[_addr % _block_size], MAX_PACKET); 00884 00885 _addr += n; 00886 _length -= n; 00887 00888 _csw.DataResidue -= n; 00889 00890 if (!_length || (_stage != PROCESS_CBW)) { 00891 _csw.Status = (_stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; 00892 _stage = (_stage == PROCESS_CBW) ? SEND_CSW : _stage; 00893 } 00894 } 00895 00896 00897 bool USBMSD::infoTransfer(void) 00898 { 00899 uint32_t n; 00900 00901 // Logical Block Address of First Block 00902 n = (_cbw.CB[2] << 24) | (_cbw.CB[3] << 16) | (_cbw.CB[4] << 8) | (_cbw.CB[5] << 0); 00903 00904 _addr = n * _block_size; 00905 00906 // Number of Blocks to transfer 00907 switch (_cbw.CB[0]) { 00908 case READ10: 00909 case WRITE10: 00910 case VERIFY10: 00911 n = (_cbw.CB[7] << 8) | (_cbw.CB[8] << 0); 00912 break; 00913 00914 case READ12: 00915 case WRITE12: 00916 n = (_cbw.CB[6] << 24) | (_cbw.CB[7] << 16) | (_cbw.CB[8] << 8) | (_cbw.CB[9] << 0); 00917 break; 00918 } 00919 00920 _length = n * _block_size; 00921 00922 if (!_cbw.DataLength) { // host requests no data 00923 _csw.Status = CSW_FAILED; 00924 sendCSW(); 00925 return false; 00926 } 00927 00928 if (_cbw.DataLength != _length) { 00929 if ((_cbw.Flags & 0x80) != 0) { 00930 endpoint_stall(_bulk_in); 00931 } else { 00932 endpoint_stall(_bulk_out); 00933 } 00934 00935 _csw.Status = CSW_FAILED; 00936 sendCSW(); 00937 return false; 00938 } 00939 00940 return true; 00941 } 00942 00943 void USBMSD::msd_reset() 00944 { 00945 _stage = READ_CBW; 00946 }
Generated on Tue Jul 12 2022 13:55:03 by
1.7.2