Simple USBHost library for STM32F746NG Discovery board. Only either the Fastspeed or the Highspeed port can be used( not both together)

Dependents:   DISCO-F746NG_USB_Host

Fork of KL46Z-USBHost by Norimasa Okamoto

Committer:
DieterGraef
Date:
Fri Jun 17 09:00:35 2016 +0000
Revision:
25:7d6d9fc471bf
Parent:
24:5396b6a93262
USB Host now works with both Interfaces even in parallel. Some changes in the USB MSD driver to make it operable

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 14:b167f2b97cb7 1 /* mbed USBHost Library
va009039 14:b167f2b97cb7 2 * Copyright (c) 2006-2013 ARM Limited
va009039 14:b167f2b97cb7 3 *
va009039 14:b167f2b97cb7 4 * Licensed under the Apache License, Version 2.0 (the "License");
va009039 14:b167f2b97cb7 5 * you may not use this file except in compliance with the License.
va009039 14:b167f2b97cb7 6 * You may obtain a copy of the License at
va009039 14:b167f2b97cb7 7 *
va009039 14:b167f2b97cb7 8 * http://www.apache.org/licenses/LICENSE-2.0
va009039 14:b167f2b97cb7 9 *
va009039 14:b167f2b97cb7 10 * Unless required by applicable law or agreed to in writing, software
va009039 14:b167f2b97cb7 11 * distributed under the License is distributed on an "AS IS" BASIS,
va009039 14:b167f2b97cb7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
va009039 14:b167f2b97cb7 13 * See the License for the specific language governing permissions and
va009039 14:b167f2b97cb7 14 * limitations under the License.
va009039 14:b167f2b97cb7 15 */
va009039 14:b167f2b97cb7 16
va009039 14:b167f2b97cb7 17 #include "USBHostMSD.h"
va009039 14:b167f2b97cb7 18
va009039 14:b167f2b97cb7 19 #if USBHOST_MSD
va009039 14:b167f2b97cb7 20
va009039 14:b167f2b97cb7 21 #include "dbg.h"
va009039 14:b167f2b97cb7 22
va009039 14:b167f2b97cb7 23 #define CBW_SIGNATURE 0x43425355
va009039 14:b167f2b97cb7 24 #define CSW_SIGNATURE 0x53425355
va009039 14:b167f2b97cb7 25
DieterGraef 25:7d6d9fc471bf 26
va009039 14:b167f2b97cb7 27 #define DEVICE_TO_HOST 0x80
va009039 14:b167f2b97cb7 28 #define HOST_TO_DEVICE 0x00
va009039 14:b167f2b97cb7 29
va009039 14:b167f2b97cb7 30 #define GET_MAX_LUN (0xFE)
va009039 14:b167f2b97cb7 31 #define BO_MASS_STORAGE_RESET (0xFF)
va009039 14:b167f2b97cb7 32
DieterGraef 25:7d6d9fc471bf 33 USBHostMSD::USBHostMSD(const char * rootdir,int Interface) : FATFileSystem(rootdir)
va009039 14:b167f2b97cb7 34 {
DieterGraef 24:5396b6a93262 35 host = USBHost::getHostInst(Interface);
va009039 14:b167f2b97cb7 36 init();
va009039 14:b167f2b97cb7 37 }
va009039 14:b167f2b97cb7 38
va009039 14:b167f2b97cb7 39 void USBHostMSD::init() {
va009039 14:b167f2b97cb7 40 dev_connected = false;
va009039 14:b167f2b97cb7 41 dev = NULL;
va009039 14:b167f2b97cb7 42 bulk_in = NULL;
va009039 14:b167f2b97cb7 43 bulk_out = NULL;
va009039 14:b167f2b97cb7 44 dev_connected = false;
va009039 14:b167f2b97cb7 45 blockSize = 0;
va009039 14:b167f2b97cb7 46 blockCount = 0;
va009039 14:b167f2b97cb7 47 msd_intf = -1;
va009039 14:b167f2b97cb7 48 msd_device_found = false;
va009039 14:b167f2b97cb7 49 disk_init = false;
va009039 14:b167f2b97cb7 50 dev_connected = false;
va009039 14:b167f2b97cb7 51 nb_ep = 0;
va009039 14:b167f2b97cb7 52 }
va009039 14:b167f2b97cb7 53
va009039 14:b167f2b97cb7 54
va009039 14:b167f2b97cb7 55 bool USBHostMSD::connected()
va009039 14:b167f2b97cb7 56 {
va009039 14:b167f2b97cb7 57 return dev_connected;
va009039 14:b167f2b97cb7 58 }
va009039 14:b167f2b97cb7 59
va009039 14:b167f2b97cb7 60 bool USBHostMSD::connect()
va009039 14:b167f2b97cb7 61 {
va009039 14:b167f2b97cb7 62
va009039 14:b167f2b97cb7 63 if (dev_connected) {
va009039 14:b167f2b97cb7 64 return true;
va009039 14:b167f2b97cb7 65 }
va009039 14:b167f2b97cb7 66
va009039 14:b167f2b97cb7 67 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
va009039 14:b167f2b97cb7 68 if ((dev = host->getDevice(i)) != NULL) {
DieterGraef 25:7d6d9fc471bf 69
va009039 14:b167f2b97cb7 70 USB_DBG("Trying to connect MSD device\r\n");
DieterGraef 25:7d6d9fc471bf 71
va009039 14:b167f2b97cb7 72 if(host->enumerate(dev, this))
va009039 14:b167f2b97cb7 73 break;
va009039 14:b167f2b97cb7 74
va009039 14:b167f2b97cb7 75 if (msd_device_found) {
va009039 14:b167f2b97cb7 76 bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN);
va009039 14:b167f2b97cb7 77 bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT);
DieterGraef 25:7d6d9fc471bf 78
va009039 14:b167f2b97cb7 79 if (!bulk_in || !bulk_out)
va009039 14:b167f2b97cb7 80 continue;
DieterGraef 25:7d6d9fc471bf 81
va009039 14:b167f2b97cb7 82 USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, msd_intf);
va009039 14:b167f2b97cb7 83 dev->setName("MSD", msd_intf);
va009039 14:b167f2b97cb7 84 host->registerDriver(dev, msd_intf, this, &USBHostMSD::init);
va009039 14:b167f2b97cb7 85
va009039 14:b167f2b97cb7 86 dev_connected = true;
va009039 14:b167f2b97cb7 87 return true;
va009039 14:b167f2b97cb7 88 }
va009039 14:b167f2b97cb7 89 } //if()
va009039 14:b167f2b97cb7 90 } //for()
va009039 14:b167f2b97cb7 91 init();
va009039 14:b167f2b97cb7 92 return false;
va009039 14:b167f2b97cb7 93 }
va009039 14:b167f2b97cb7 94
va009039 14:b167f2b97cb7 95 /*virtual*/ void USBHostMSD::setVidPid(uint16_t vid, uint16_t pid)
va009039 14:b167f2b97cb7 96 {
va009039 14:b167f2b97cb7 97 // we don't check VID/PID for MSD driver
va009039 14:b167f2b97cb7 98 }
va009039 14:b167f2b97cb7 99
va009039 14:b167f2b97cb7 100 /*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
va009039 14:b167f2b97cb7 101 {
va009039 14:b167f2b97cb7 102 if ((msd_intf == -1) &&
va009039 14:b167f2b97cb7 103 (intf_class == MSD_CLASS) &&
va009039 14:b167f2b97cb7 104 (intf_subclass == 0x06) &&
va009039 14:b167f2b97cb7 105 (intf_protocol == 0x50)) {
va009039 14:b167f2b97cb7 106 msd_intf = intf_nb;
va009039 14:b167f2b97cb7 107 return true;
va009039 14:b167f2b97cb7 108 }
va009039 14:b167f2b97cb7 109 return false;
va009039 14:b167f2b97cb7 110 }
va009039 14:b167f2b97cb7 111
va009039 14:b167f2b97cb7 112 /*virtual*/ bool USBHostMSD::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
va009039 14:b167f2b97cb7 113 {
va009039 14:b167f2b97cb7 114 if (intf_nb == msd_intf) {
va009039 14:b167f2b97cb7 115 if (type == BULK_ENDPOINT) {
va009039 14:b167f2b97cb7 116 nb_ep++;
va009039 14:b167f2b97cb7 117 if (nb_ep == 2)
va009039 14:b167f2b97cb7 118 msd_device_found = true;
va009039 14:b167f2b97cb7 119 return true;
va009039 14:b167f2b97cb7 120 }
va009039 14:b167f2b97cb7 121 }
va009039 14:b167f2b97cb7 122 return false;
va009039 14:b167f2b97cb7 123 }
va009039 14:b167f2b97cb7 124
va009039 14:b167f2b97cb7 125
DieterGraef 25:7d6d9fc471bf 126 int USBHostMSD::testUnitReady(int i) {
va009039 14:b167f2b97cb7 127 USB_DBG("Test unit ready");
DieterGraef 25:7d6d9fc471bf 128 uint8_t cmd[6] = {0,0,0,0,0,0};
DieterGraef 25:7d6d9fc471bf 129 //SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len)
DieterGraef 25:7d6d9fc471bf 130 //return SCSITransfer(cmd, 6, DEVICE_TO_HOST, 0, 0);
DieterGraef 25:7d6d9fc471bf 131 int res = 0;
DieterGraef 25:7d6d9fc471bf 132
DieterGraef 25:7d6d9fc471bf 133 cbw.Signature = CBW_SIGNATURE;
DieterGraef 25:7d6d9fc471bf 134 cbw.Tag = 0;
DieterGraef 25:7d6d9fc471bf 135 cbw.DataLength = 0;
DieterGraef 25:7d6d9fc471bf 136 cbw.Flags = DEVICE_TO_HOST;
DieterGraef 25:7d6d9fc471bf 137 cbw.LUN = 0;
DieterGraef 25:7d6d9fc471bf 138 cbw.CBLength = 6;
DieterGraef 25:7d6d9fc471bf 139 memset(cbw.CB,0,sizeof(cbw.CB));
DieterGraef 25:7d6d9fc471bf 140 if (cmd) {
DieterGraef 25:7d6d9fc471bf 141 memcpy(cbw.CB,cmd,6);
DieterGraef 25:7d6d9fc471bf 142 }
DieterGraef 25:7d6d9fc471bf 143
DieterGraef 25:7d6d9fc471bf 144 // send the cbw
DieterGraef 25:7d6d9fc471bf 145 USB_DBG("Send CBW");
DieterGraef 25:7d6d9fc471bf 146 res = host->bulkWrite(dev, bulk_out,(uint8_t *)&cbw, 31);
DieterGraef 25:7d6d9fc471bf 147 if (checkResult(res, bulk_out))
DieterGraef 25:7d6d9fc471bf 148 return -1;
DieterGraef 25:7d6d9fc471bf 149
DieterGraef 25:7d6d9fc471bf 150 wait_ms(6000*i);
DieterGraef 25:7d6d9fc471bf 151
DieterGraef 25:7d6d9fc471bf 152 // status stage
DieterGraef 25:7d6d9fc471bf 153 csw.Signature = 0;
DieterGraef 25:7d6d9fc471bf 154 USB_DBG("Read CSW");
DieterGraef 25:7d6d9fc471bf 155 res = host->bulkRead(dev, bulk_in,(uint8_t *)&csw, 13);
DieterGraef 25:7d6d9fc471bf 156 if (checkResult(res, bulk_in))
DieterGraef 25:7d6d9fc471bf 157 return -1;
DieterGraef 25:7d6d9fc471bf 158
DieterGraef 25:7d6d9fc471bf 159 if (csw.Signature != CSW_SIGNATURE) {
DieterGraef 25:7d6d9fc471bf 160 return -1;
DieterGraef 25:7d6d9fc471bf 161 }
DieterGraef 25:7d6d9fc471bf 162
DieterGraef 25:7d6d9fc471bf 163 USB_DBG("recv csw: status: %d", csw.Status);
DieterGraef 25:7d6d9fc471bf 164
DieterGraef 25:7d6d9fc471bf 165 // ModeSense?
DieterGraef 25:7d6d9fc471bf 166 if ((csw.Status == 1) && (cmd[0] != 0x03)) {
DieterGraef 25:7d6d9fc471bf 167 USB_DBG("request mode sense");
DieterGraef 25:7d6d9fc471bf 168 return SCSIRequestSense();
DieterGraef 25:7d6d9fc471bf 169 }
DieterGraef 25:7d6d9fc471bf 170
DieterGraef 25:7d6d9fc471bf 171 // perform reset recovery
DieterGraef 25:7d6d9fc471bf 172 if ((csw.Status == 2) && (cmd[0] != 0x03)) {
DieterGraef 25:7d6d9fc471bf 173
DieterGraef 25:7d6d9fc471bf 174 // send Bulk-Only Mass Storage Reset request
DieterGraef 25:7d6d9fc471bf 175 res = host->controlWrite( dev,
DieterGraef 25:7d6d9fc471bf 176 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
DieterGraef 25:7d6d9fc471bf 177 BO_MASS_STORAGE_RESET,
DieterGraef 25:7d6d9fc471bf 178 0, msd_intf, NULL, 0);
DieterGraef 25:7d6d9fc471bf 179
DieterGraef 25:7d6d9fc471bf 180 // unstall both endpoints
DieterGraef 25:7d6d9fc471bf 181 res = host->controlWrite( dev,
DieterGraef 25:7d6d9fc471bf 182 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
DieterGraef 25:7d6d9fc471bf 183 CLEAR_FEATURE,
DieterGraef 25:7d6d9fc471bf 184 0, bulk_in->getAddress(), NULL, 0);
DieterGraef 25:7d6d9fc471bf 185
DieterGraef 25:7d6d9fc471bf 186 res = host->controlWrite( dev,
DieterGraef 25:7d6d9fc471bf 187 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
DieterGraef 25:7d6d9fc471bf 188 CLEAR_FEATURE,
DieterGraef 25:7d6d9fc471bf 189 0, bulk_out->getAddress(), NULL, 0);
DieterGraef 25:7d6d9fc471bf 190
DieterGraef 25:7d6d9fc471bf 191 }
DieterGraef 25:7d6d9fc471bf 192
DieterGraef 25:7d6d9fc471bf 193 return csw.Status;
va009039 14:b167f2b97cb7 194 }
va009039 14:b167f2b97cb7 195
va009039 14:b167f2b97cb7 196
va009039 14:b167f2b97cb7 197 int USBHostMSD::readCapacity() {
va009039 14:b167f2b97cb7 198 USB_DBG("Read capacity");
va009039 14:b167f2b97cb7 199 uint8_t cmd[10] = {0x25,0,0,0,0,0,0,0,0,0};
va009039 14:b167f2b97cb7 200 uint8_t result[8];
va009039 14:b167f2b97cb7 201 int status = SCSITransfer(cmd, 10, DEVICE_TO_HOST, result, 8);
va009039 14:b167f2b97cb7 202 if (status == 0) {
va009039 14:b167f2b97cb7 203 blockCount = (result[0] << 24) | (result[1] << 16) | (result[2] << 8) | result[3];
va009039 14:b167f2b97cb7 204 blockSize = (result[4] << 24) | (result[5] << 16) | (result[6] << 8) | result[7];
va009039 14:b167f2b97cb7 205 USB_INFO("MSD [dev: %p] - blockCount: %lld, blockSize: %d, Capacity: %lld\r\n", dev, blockCount, blockSize, blockCount*blockSize);
va009039 14:b167f2b97cb7 206 }
va009039 14:b167f2b97cb7 207 return status;
va009039 14:b167f2b97cb7 208 }
va009039 14:b167f2b97cb7 209
va009039 14:b167f2b97cb7 210
va009039 14:b167f2b97cb7 211 int USBHostMSD::SCSIRequestSense() {
va009039 14:b167f2b97cb7 212 USB_DBG("Request sense");
va009039 14:b167f2b97cb7 213 uint8_t cmd[6] = {0x03,0,0,0,18,0};
va009039 14:b167f2b97cb7 214 uint8_t result[18];
va009039 14:b167f2b97cb7 215 int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 18);
va009039 14:b167f2b97cb7 216 return status;
va009039 14:b167f2b97cb7 217 }
va009039 14:b167f2b97cb7 218
va009039 14:b167f2b97cb7 219
va009039 14:b167f2b97cb7 220 int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) {
va009039 14:b167f2b97cb7 221 USB_DBG("Inquiry");
va009039 14:b167f2b97cb7 222 uint8_t evpd = (page_code == 0) ? 0 : 1;
va009039 14:b167f2b97cb7 223 uint8_t cmd[6] = {0x12, uint8_t((lun << 5) | evpd), page_code, 0, 36, 0};
va009039 14:b167f2b97cb7 224 uint8_t result[36];
va009039 14:b167f2b97cb7 225 int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 36);
va009039 14:b167f2b97cb7 226 if (status == 0) {
va009039 14:b167f2b97cb7 227 char vid_pid[17];
va009039 14:b167f2b97cb7 228 memcpy(vid_pid, &result[8], 8);
va009039 14:b167f2b97cb7 229 vid_pid[8] = 0;
va009039 14:b167f2b97cb7 230 USB_INFO("MSD [dev: %p] - Vendor ID: %s", dev, vid_pid);
va009039 14:b167f2b97cb7 231
va009039 14:b167f2b97cb7 232 memcpy(vid_pid, &result[16], 16);
va009039 14:b167f2b97cb7 233 vid_pid[16] = 0;
va009039 14:b167f2b97cb7 234 USB_INFO("MSD [dev: %p] - Product ID: %s", dev, vid_pid);
va009039 14:b167f2b97cb7 235
va009039 14:b167f2b97cb7 236 memcpy(vid_pid, &result[32], 4);
va009039 14:b167f2b97cb7 237 vid_pid[4] = 0;
va009039 14:b167f2b97cb7 238 USB_INFO("MSD [dev: %p] - Product rev: %s", dev, vid_pid);
va009039 14:b167f2b97cb7 239 }
va009039 14:b167f2b97cb7 240 return status;
va009039 14:b167f2b97cb7 241 }
va009039 14:b167f2b97cb7 242
va009039 14:b167f2b97cb7 243 int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) {
va009039 14:b167f2b97cb7 244 // if ep stalled: send clear feature
va009039 14:b167f2b97cb7 245 if (res == USB_TYPE_STALL_ERROR) {
va009039 14:b167f2b97cb7 246 res = host->controlWrite( dev,
va009039 14:b167f2b97cb7 247 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
va009039 14:b167f2b97cb7 248 CLEAR_FEATURE,
va009039 14:b167f2b97cb7 249 0, ep->getAddress(), NULL, 0);
va009039 14:b167f2b97cb7 250 // set state to IDLE if clear feature successful
va009039 14:b167f2b97cb7 251 if (res == USB_TYPE_OK) {
va009039 14:b167f2b97cb7 252 ep->setState(USB_TYPE_IDLE);
va009039 14:b167f2b97cb7 253 }
va009039 14:b167f2b97cb7 254 }
va009039 14:b167f2b97cb7 255
va009039 14:b167f2b97cb7 256 if (res != USB_TYPE_OK)
va009039 14:b167f2b97cb7 257 return -1;
va009039 14:b167f2b97cb7 258
va009039 14:b167f2b97cb7 259 return 0;
va009039 14:b167f2b97cb7 260 }
va009039 14:b167f2b97cb7 261
va009039 14:b167f2b97cb7 262
va009039 14:b167f2b97cb7 263 int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) {
va009039 14:b167f2b97cb7 264
va009039 14:b167f2b97cb7 265 int res = 0;
va009039 14:b167f2b97cb7 266
va009039 14:b167f2b97cb7 267 cbw.Signature = CBW_SIGNATURE;
va009039 14:b167f2b97cb7 268 cbw.Tag = 0;
va009039 14:b167f2b97cb7 269 cbw.DataLength = transfer_len;
va009039 14:b167f2b97cb7 270 cbw.Flags = flags;
va009039 14:b167f2b97cb7 271 cbw.LUN = 0;
va009039 14:b167f2b97cb7 272 cbw.CBLength = cmd_len;
va009039 14:b167f2b97cb7 273 memset(cbw.CB,0,sizeof(cbw.CB));
va009039 14:b167f2b97cb7 274 if (cmd) {
va009039 14:b167f2b97cb7 275 memcpy(cbw.CB,cmd,cmd_len);
va009039 14:b167f2b97cb7 276 }
va009039 14:b167f2b97cb7 277
va009039 14:b167f2b97cb7 278 // send the cbw
va009039 14:b167f2b97cb7 279 USB_DBG("Send CBW");
va009039 14:b167f2b97cb7 280 res = host->bulkWrite(dev, bulk_out,(uint8_t *)&cbw, 31);
va009039 14:b167f2b97cb7 281 if (checkResult(res, bulk_out))
va009039 14:b167f2b97cb7 282 return -1;
va009039 14:b167f2b97cb7 283
va009039 14:b167f2b97cb7 284 // data stage if needed
va009039 14:b167f2b97cb7 285 if (data) {
va009039 14:b167f2b97cb7 286 USB_DBG("data stage");
va009039 14:b167f2b97cb7 287 if (flags == HOST_TO_DEVICE) {
DieterGraef 25:7d6d9fc471bf 288
va009039 14:b167f2b97cb7 289 res = host->bulkWrite(dev, bulk_out, data, transfer_len);
va009039 14:b167f2b97cb7 290 if (checkResult(res, bulk_out))
va009039 14:b167f2b97cb7 291 return -1;
va009039 14:b167f2b97cb7 292
va009039 14:b167f2b97cb7 293 } else if (flags == DEVICE_TO_HOST) {
va009039 14:b167f2b97cb7 294
va009039 14:b167f2b97cb7 295 res = host->bulkRead(dev, bulk_in, data, transfer_len);
va009039 14:b167f2b97cb7 296 if (checkResult(res, bulk_in))
va009039 14:b167f2b97cb7 297 return -1;
va009039 14:b167f2b97cb7 298 }
va009039 14:b167f2b97cb7 299 }
va009039 14:b167f2b97cb7 300
va009039 14:b167f2b97cb7 301 // status stage
va009039 14:b167f2b97cb7 302 csw.Signature = 0;
va009039 14:b167f2b97cb7 303 USB_DBG("Read CSW");
va009039 14:b167f2b97cb7 304 res = host->bulkRead(dev, bulk_in,(uint8_t *)&csw, 13);
va009039 14:b167f2b97cb7 305 if (checkResult(res, bulk_in))
va009039 14:b167f2b97cb7 306 return -1;
va009039 14:b167f2b97cb7 307
va009039 14:b167f2b97cb7 308 if (csw.Signature != CSW_SIGNATURE) {
va009039 14:b167f2b97cb7 309 return -1;
va009039 14:b167f2b97cb7 310 }
DieterGraef 25:7d6d9fc471bf 311
va009039 14:b167f2b97cb7 312 USB_DBG("recv csw: status: %d", csw.Status);
va009039 14:b167f2b97cb7 313
va009039 14:b167f2b97cb7 314 // ModeSense?
va009039 14:b167f2b97cb7 315 if ((csw.Status == 1) && (cmd[0] != 0x03)) {
va009039 14:b167f2b97cb7 316 USB_DBG("request mode sense");
va009039 14:b167f2b97cb7 317 return SCSIRequestSense();
va009039 14:b167f2b97cb7 318 }
DieterGraef 25:7d6d9fc471bf 319
va009039 14:b167f2b97cb7 320 // perform reset recovery
va009039 14:b167f2b97cb7 321 if ((csw.Status == 2) && (cmd[0] != 0x03)) {
DieterGraef 25:7d6d9fc471bf 322
va009039 14:b167f2b97cb7 323 // send Bulk-Only Mass Storage Reset request
va009039 14:b167f2b97cb7 324 res = host->controlWrite( dev,
va009039 14:b167f2b97cb7 325 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
va009039 14:b167f2b97cb7 326 BO_MASS_STORAGE_RESET,
va009039 14:b167f2b97cb7 327 0, msd_intf, NULL, 0);
DieterGraef 25:7d6d9fc471bf 328
va009039 14:b167f2b97cb7 329 // unstall both endpoints
va009039 14:b167f2b97cb7 330 res = host->controlWrite( dev,
va009039 14:b167f2b97cb7 331 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
va009039 14:b167f2b97cb7 332 CLEAR_FEATURE,
va009039 14:b167f2b97cb7 333 0, bulk_in->getAddress(), NULL, 0);
DieterGraef 25:7d6d9fc471bf 334
va009039 14:b167f2b97cb7 335 res = host->controlWrite( dev,
va009039 14:b167f2b97cb7 336 USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
va009039 14:b167f2b97cb7 337 CLEAR_FEATURE,
va009039 14:b167f2b97cb7 338 0, bulk_out->getAddress(), NULL, 0);
DieterGraef 25:7d6d9fc471bf 339
va009039 14:b167f2b97cb7 340 }
va009039 14:b167f2b97cb7 341
va009039 14:b167f2b97cb7 342 return csw.Status;
va009039 14:b167f2b97cb7 343 }
va009039 14:b167f2b97cb7 344
va009039 14:b167f2b97cb7 345
DieterGraef 25:7d6d9fc471bf 346 int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint32_t nbBlock, int direction) {
va009039 14:b167f2b97cb7 347 uint8_t cmd[10];
va009039 14:b167f2b97cb7 348 memset(cmd,0,10);
va009039 14:b167f2b97cb7 349 cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
va009039 14:b167f2b97cb7 350
va009039 14:b167f2b97cb7 351 cmd[2] = (block >> 24) & 0xff;
va009039 14:b167f2b97cb7 352 cmd[3] = (block >> 16) & 0xff;
va009039 14:b167f2b97cb7 353 cmd[4] = (block >> 8) & 0xff;
va009039 14:b167f2b97cb7 354 cmd[5] = block & 0xff;
va009039 14:b167f2b97cb7 355
va009039 14:b167f2b97cb7 356 cmd[7] = (nbBlock >> 8) & 0xff;
va009039 14:b167f2b97cb7 357 cmd[8] = nbBlock & 0xff;
va009039 14:b167f2b97cb7 358
va009039 14:b167f2b97cb7 359 return SCSITransfer(cmd, 10, direction, buf, blockSize*nbBlock);
va009039 14:b167f2b97cb7 360 }
va009039 14:b167f2b97cb7 361
va009039 14:b167f2b97cb7 362 int USBHostMSD::getMaxLun() {
va009039 14:b167f2b97cb7 363 uint8_t buf[1], res;
va009039 14:b167f2b97cb7 364 res = host->controlRead( dev, USB_RECIPIENT_INTERFACE | USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS,
va009039 14:b167f2b97cb7 365 0xfe, 0, msd_intf, buf, 1);
va009039 14:b167f2b97cb7 366 USB_DBG("max lun: %d", buf[0]);
va009039 14:b167f2b97cb7 367 return res;
va009039 14:b167f2b97cb7 368 }
va009039 14:b167f2b97cb7 369
va009039 14:b167f2b97cb7 370 int USBHostMSD::disk_initialize() {
va009039 14:b167f2b97cb7 371 USB_DBG("FILESYSTEM: init");
va009039 14:b167f2b97cb7 372 /* U16 */int i, timeout = 10;
DieterGraef 25:7d6d9fc471bf 373
va009039 14:b167f2b97cb7 374 getMaxLun();
DieterGraef 25:7d6d9fc471bf 375
va009039 14:b167f2b97cb7 376 for (i = 0; i < timeout; i++) {
va009039 14:b167f2b97cb7 377 wait_ms(100); //Thread::wait(100);
DieterGraef 25:7d6d9fc471bf 378 if (!testUnitReady(i+1))
va009039 14:b167f2b97cb7 379 break;
DieterGraef 25:7d6d9fc471bf 380 printf("TestUnitReady %d\r\n",i);
DieterGraef 25:7d6d9fc471bf 381 if(i>1)
DieterGraef 25:7d6d9fc471bf 382 {
DieterGraef 25:7d6d9fc471bf 383 host->controlWrite( dev,
DieterGraef 25:7d6d9fc471bf 384 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
DieterGraef 25:7d6d9fc471bf 385 BO_MASS_STORAGE_RESET,
DieterGraef 25:7d6d9fc471bf 386 0, msd_intf, NULL, 0);
DieterGraef 25:7d6d9fc471bf 387
DieterGraef 25:7d6d9fc471bf 388 };
va009039 14:b167f2b97cb7 389 }
DieterGraef 25:7d6d9fc471bf 390
va009039 14:b167f2b97cb7 391 if (i == timeout) {
va009039 14:b167f2b97cb7 392 disk_init = false;
va009039 14:b167f2b97cb7 393 return -1;
va009039 14:b167f2b97cb7 394 }
DieterGraef 25:7d6d9fc471bf 395
va009039 14:b167f2b97cb7 396 inquiry(0, 0);
va009039 14:b167f2b97cb7 397 disk_init = 1;
va009039 14:b167f2b97cb7 398 return readCapacity();
va009039 14:b167f2b97cb7 399 }
va009039 14:b167f2b97cb7 400
va009039 20:9827f135ccb6 401 int USBHostMSD::disk_write(const uint8_t *buffer, uint64_t sector, uint8_t count) {
va009039 20:9827f135ccb6 402 USB_DBG("FILESYSTEM: write sector: %lld, count: %d", sector, count);
va009039 14:b167f2b97cb7 403 if (!disk_init) {
va009039 14:b167f2b97cb7 404 disk_initialize();
va009039 14:b167f2b97cb7 405 }
va009039 14:b167f2b97cb7 406 if (!disk_init)
va009039 14:b167f2b97cb7 407 return -1;
DieterGraef 25:7d6d9fc471bf 408 if (count>0x800000)
DieterGraef 25:7d6d9fc471bf 409 return -1;
DieterGraef 25:7d6d9fc471bf 410 return dataTransfer((uint8_t *)buffer, sector,(uint32_t) count, HOST_TO_DEVICE);
va009039 14:b167f2b97cb7 411 }
va009039 14:b167f2b97cb7 412
va009039 20:9827f135ccb6 413 int USBHostMSD::disk_read(uint8_t * buffer, uint64_t sector, uint8_t count) {
va009039 20:9827f135ccb6 414 USB_DBG("FILESYSTEM: read sector: %lld, count: %d", sector, count);
va009039 14:b167f2b97cb7 415 if (!disk_init) {
va009039 14:b167f2b97cb7 416 disk_initialize();
va009039 14:b167f2b97cb7 417 }
va009039 14:b167f2b97cb7 418 if (!disk_init)
va009039 14:b167f2b97cb7 419 return -1;
DieterGraef 25:7d6d9fc471bf 420 if (count>0x800000)
DieterGraef 25:7d6d9fc471bf 421 return -1;
DieterGraef 25:7d6d9fc471bf 422 return dataTransfer((uint8_t *)buffer, sector,(uint32_t) count, DEVICE_TO_HOST);
va009039 14:b167f2b97cb7 423 }
va009039 14:b167f2b97cb7 424
DieterGraef 25:7d6d9fc471bf 425
va009039 14:b167f2b97cb7 426 uint64_t USBHostMSD::disk_sectors() {
va009039 14:b167f2b97cb7 427 USB_DBG("FILESYSTEM: sectors");
va009039 14:b167f2b97cb7 428 if (!disk_init) {
va009039 14:b167f2b97cb7 429 disk_initialize();
va009039 14:b167f2b97cb7 430 }
va009039 14:b167f2b97cb7 431 if (!disk_init)
va009039 14:b167f2b97cb7 432 return 0;
va009039 14:b167f2b97cb7 433 return blockCount;
va009039 14:b167f2b97cb7 434 }
va009039 14:b167f2b97cb7 435
va009039 14:b167f2b97cb7 436 #endif