USB lib Joerg

Fork of USBHost_DISCO-F746NG by Dieter Graef

Committer:
schmalzl
Date:
Wed Nov 30 10:51:48 2016 +0000
Revision:
26:49c13dfc95d0
Parent:
25:7d6d9fc471bf
Turbo Ede v1

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