Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
USBHostMSD.cpp
00001 /* mbed USBHost Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "USBHostMSD.h" 00018 00019 #if USBHOST_MSD 00020 #include "dbg.h" 00021 00022 #define CBW_SIGNATURE 0x43425355 00023 #define CSW_SIGNATURE 0x53425355 00024 00025 #define DEVICE_TO_HOST 0x80 00026 #define HOST_TO_DEVICE 0x00 00027 00028 #define GET_MAX_LUN (0xFE) 00029 #define BO_MASS_STORAGE_RESET (0xFF) 00030 00031 USBHostMSD::USBHostMSD() 00032 { 00033 host = USBHost::getHostInst(); 00034 /* register an object in FAT */ 00035 00036 init_usb(); 00037 } 00038 00039 void USBHostMSD::init_usb() 00040 { 00041 dev_connected = false; 00042 dev = NULL; 00043 bulk_in = NULL; 00044 bulk_out = NULL; 00045 dev_connected = false; 00046 blockSize = 0; 00047 blockCount = 0; 00048 msd_intf = -1; 00049 msd_device_found = false; 00050 disk_init = false; 00051 dev_connected = false; 00052 nb_ep = 0; 00053 } 00054 00055 00056 bool USBHostMSD::connected() 00057 { 00058 return dev_connected; 00059 } 00060 00061 bool USBHostMSD::connect() 00062 { 00063 00064 if (dev_connected) { 00065 return true; 00066 } 00067 00068 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { 00069 if ((dev = host->getDevice(i)) != NULL) { 00070 00071 USB_DBG("Trying to connect MSD device\r\n"); 00072 00073 if(host->enumerate(dev, this)) 00074 break; 00075 00076 if (msd_device_found) { 00077 /* As this is done in a specific thread 00078 * this lock is taken to avoid to process a disconnection in 00079 * usb process during the device registering */ 00080 USBHost::Lock Lock(host); 00081 00082 bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN); 00083 bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT); 00084 00085 if (!bulk_in || !bulk_out) 00086 continue; 00087 00088 USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, msd_intf); 00089 dev->setName("MSD", msd_intf); 00090 host->registerDriver(dev, msd_intf, this, &USBHostMSD::init_usb); 00091 00092 dev_connected = true; 00093 return true; 00094 } 00095 } //if() 00096 } //for() 00097 init_usb(); 00098 return false; 00099 } 00100 00101 /*virtual*/ void USBHostMSD::setVidPid(uint16_t vid, uint16_t pid) 00102 { 00103 // we don't check VID/PID for MSD driver 00104 } 00105 00106 /*virtual*/ bool USBHostMSD::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed 00107 { 00108 if ((msd_intf == -1) && 00109 (intf_class == MSD_CLASS) && 00110 (intf_subclass == 0x06) && 00111 (intf_protocol == 0x50)) { 00112 msd_intf = intf_nb; 00113 return true; 00114 } 00115 return false; 00116 } 00117 00118 /*virtual*/ bool USBHostMSD::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00119 { 00120 if (intf_nb == msd_intf) { 00121 if (type == BULK_ENDPOINT) { 00122 nb_ep++; 00123 if (nb_ep == 2) 00124 msd_device_found = true; 00125 return true; 00126 } 00127 } 00128 return false; 00129 } 00130 00131 00132 int USBHostMSD::testUnitReady() 00133 { 00134 USB_DBG("Test unit ready"); 00135 return SCSITransfer(NULL, 6, DEVICE_TO_HOST, 0, 0); 00136 } 00137 00138 00139 int USBHostMSD::readCapacity() 00140 { 00141 USB_DBG("Read capacity"); 00142 uint8_t cmd[10] = {0x25,0,0,0,0,0,0,0,0,0}; 00143 uint8_t result[8]; 00144 int status = SCSITransfer(cmd, 10, DEVICE_TO_HOST, result, 8); 00145 if (status == 0) { 00146 blockCount = (result[0] << 24) | (result[1] << 16) | (result[2] << 8) | result[3]; 00147 blockSize = (result[4] << 24) | (result[5] << 16) | (result[6] << 8) | result[7]; 00148 USB_INFO("MSD [dev: %p] - blockCount: %u, blockSize: %d, Capacity: %d\r\n", dev, blockCount, blockSize, blockCount*blockSize); 00149 } 00150 return status; 00151 } 00152 00153 00154 int USBHostMSD::SCSIRequestSense() 00155 { 00156 USB_DBG("Request sense"); 00157 uint8_t cmd[6] = {0x03,0,0,0,18,0}; 00158 uint8_t result[18]; 00159 int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 18); 00160 return status; 00161 } 00162 00163 00164 int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) 00165 { 00166 USB_DBG("Inquiry"); 00167 uint8_t evpd = (page_code == 0) ? 0 : 1; 00168 uint8_t cmd[6] = {0x12, uint8_t((lun << 5) | evpd), page_code, 0, 36, 0}; 00169 uint8_t result[36]; 00170 int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 36); 00171 if (status == 0) { 00172 char vid_pid[17]; 00173 memcpy(vid_pid, &result[8], 8); 00174 vid_pid[8] = 0; 00175 USB_INFO("MSD [dev: %p] - Vendor ID: %s", dev, vid_pid); 00176 00177 memcpy(vid_pid, &result[16], 16); 00178 vid_pid[16] = 0; 00179 USB_INFO("MSD [dev: %p] - Product ID: %s", dev, vid_pid); 00180 00181 memcpy(vid_pid, &result[32], 4); 00182 vid_pid[4] = 0; 00183 USB_INFO("MSD [dev: %p] - Product rev: %s", dev, vid_pid); 00184 } 00185 return status; 00186 } 00187 00188 int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) 00189 { 00190 // if ep stalled: send clear feature 00191 if (res == USB_TYPE_STALL_ERROR) { 00192 res = host->controlWrite( dev, 00193 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, 00194 CLEAR_FEATURE, 00195 0, ep->getAddress(), NULL, 0); 00196 // set state to IDLE if clear feature successful 00197 if (res == USB_TYPE_OK) { 00198 ep->setState(USB_TYPE_IDLE); 00199 } 00200 } 00201 00202 if (res != USB_TYPE_OK) 00203 return -1; 00204 00205 return 0; 00206 } 00207 00208 00209 int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) 00210 { 00211 00212 int res = 0; 00213 00214 cbw.Signature = CBW_SIGNATURE; 00215 cbw.Tag = 0; 00216 cbw.DataLength = transfer_len; 00217 cbw.Flags = flags; 00218 cbw.LUN = 0; 00219 cbw.CBLength = cmd_len; 00220 memset(cbw.CB,0,sizeof(cbw.CB)); 00221 if (cmd) { 00222 memcpy(cbw.CB,cmd,cmd_len); 00223 } 00224 00225 // send the cbw 00226 USB_DBG("Send CBW"); 00227 res = host->bulkWrite(dev, bulk_out,(uint8_t *)&cbw, 31); 00228 if (checkResult(res, bulk_out)) 00229 return -1; 00230 00231 // data stage if needed 00232 if (data) { 00233 USB_DBG("data stage"); 00234 if (flags == HOST_TO_DEVICE) { 00235 00236 res = host->bulkWrite(dev, bulk_out, data, transfer_len); 00237 if (checkResult(res, bulk_out)) 00238 return -1; 00239 00240 } else if (flags == DEVICE_TO_HOST) { 00241 00242 res = host->bulkRead(dev, bulk_in, data, transfer_len); 00243 if (checkResult(res, bulk_in)) 00244 return -1; 00245 } 00246 } 00247 00248 // status stage 00249 csw.Signature = 0; 00250 USB_DBG("Read CSW"); 00251 res = host->bulkRead(dev, bulk_in,(uint8_t *)&csw, 13); 00252 if (checkResult(res, bulk_in)) 00253 return -1; 00254 00255 if (csw.Signature != CSW_SIGNATURE) { 00256 return -1; 00257 } 00258 00259 USB_DBG("recv csw: status: %d", csw.Status); 00260 00261 // ModeSense? 00262 if ((csw.Status == 1) && (cmd[0] != 0x03)) { 00263 USB_DBG("request mode sense"); 00264 return SCSIRequestSense(); 00265 } 00266 00267 // perform reset recovery 00268 if ((csw.Status == 2) && (cmd[0] != 0x03)) { 00269 00270 // send Bulk-Only Mass Storage Reset request 00271 res = host->controlWrite( dev, 00272 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, 00273 BO_MASS_STORAGE_RESET, 00274 0, msd_intf, NULL, 0); 00275 00276 // unstall both endpoints 00277 res = host->controlWrite( dev, 00278 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, 00279 CLEAR_FEATURE, 00280 0, bulk_in->getAddress(), NULL, 0); 00281 00282 res = host->controlWrite( dev, 00283 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, 00284 CLEAR_FEATURE, 00285 0, bulk_out->getAddress(), NULL, 0); 00286 00287 } 00288 00289 return csw.Status; 00290 } 00291 00292 00293 int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction) 00294 { 00295 uint8_t cmd[10]; 00296 memset(cmd,0,10); 00297 cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A; 00298 00299 cmd[2] = (block >> 24) & 0xff; 00300 cmd[3] = (block >> 16) & 0xff; 00301 cmd[4] = (block >> 8) & 0xff; 00302 cmd[5] = block & 0xff; 00303 00304 cmd[7] = (nbBlock >> 8) & 0xff; 00305 cmd[8] = nbBlock & 0xff; 00306 00307 return SCSITransfer(cmd, 10, direction, buf, blockSize*nbBlock); 00308 } 00309 00310 int USBHostMSD::getMaxLun() 00311 { 00312 uint8_t buf[1], res; 00313 res = host->controlRead( dev, USB_RECIPIENT_INTERFACE | USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, 00314 0xfe, 0, msd_intf, buf, 1); 00315 USB_DBG("max lun: %d", buf[0]); 00316 return res; 00317 } 00318 00319 int USBHostMSD::init() 00320 { 00321 USB_DBG("FILESYSTEM: init"); 00322 uint16_t i, timeout = 10, ret; 00323 getMaxLun(); 00324 for (i = 0; i < timeout; i++) { 00325 Thread::wait(100); 00326 if (!testUnitReady()) 00327 break; 00328 } 00329 00330 if (i == timeout) { 00331 disk_init = false; 00332 return -1; 00333 } 00334 00335 inquiry(0, 0); 00336 disk_init = 1; 00337 return readCapacity(); 00338 } 00339 00340 int USBHostMSD::program(const void *buffer, bd_addr_t addr, bd_size_t size) 00341 { 00342 uint32_t block_number, count; 00343 uint8_t *buf = (uint8_t *)buffer; 00344 if (!disk_init) { 00345 init(); 00346 } 00347 if (!disk_init) { 00348 return -1; 00349 } 00350 block_number = addr / blockSize; 00351 count = size /blockSize; 00352 00353 for (uint32_t b = block_number; b < block_number + count; b++) { 00354 if (dataTransfer(buf, b, 1, HOST_TO_DEVICE)) 00355 return -1; 00356 buf += blockSize; 00357 } 00358 return 0; 00359 } 00360 00361 int USBHostMSD::read(void *buffer, bd_addr_t addr, bd_size_t size) 00362 { 00363 uint32_t block_number, count; 00364 uint8_t *buf = (uint8_t *)buffer; 00365 if (!disk_init) { 00366 init(); 00367 } 00368 if (!disk_init) { 00369 return -1; 00370 } 00371 block_number = addr / blockSize; 00372 count = size / blockSize; 00373 00374 for (uint32_t b = block_number; b < block_number + count; b++) { 00375 if (dataTransfer(buf, b, 1, DEVICE_TO_HOST)) 00376 return -1; 00377 buf += blockSize; 00378 } 00379 return 0; 00380 } 00381 00382 int USBHostMSD::erase(bd_addr_t addr, bd_size_t size) 00383 { 00384 return 0; 00385 } 00386 00387 bd_size_t USBHostMSD::get_read_size() const 00388 { 00389 return (disk_init ? (bd_size_t)blockSize : -1); 00390 } 00391 00392 bd_size_t USBHostMSD::get_program_size() const 00393 { 00394 return (disk_init ? (bd_size_t)blockSize : -1); 00395 } 00396 bd_size_t USBHostMSD::get_erase_size() const 00397 { 00398 return (disk_init ? (bd_size_t)blockSize : -1); 00399 } 00400 00401 bd_size_t USBHostMSD::size() const 00402 { 00403 USB_DBG("FILESYSTEM: size "); 00404 return (disk_init ? (bd_size_t)blockSize : 0); 00405 } 00406 #endif
Generated on Sun Jul 17 2022 08:25:33 by 1.7.2