updsted the USB to persuade it to build for the Dragonfly platfom

Fork of USBDevice by mbed official

Committer:
Patrickhalahan
Date:
Fri May 11 09:07:29 2018 +0000
Revision:
72:e5c300b1df2f
Parent:
51:deafa44182d9
Just enough to get SD card size to report

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 1:80ab0d068708 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
samux 1:80ab0d068708 2 *
samux 1:80ab0d068708 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 1:80ab0d068708 4 * and associated documentation files (the "Software"), to deal in the Software without
samux 1:80ab0d068708 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
samux 1:80ab0d068708 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
samux 1:80ab0d068708 7 * Software is furnished to do so, subject to the following conditions:
samux 1:80ab0d068708 8 *
samux 1:80ab0d068708 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 1:80ab0d068708 10 * substantial portions of the Software.
samux 1:80ab0d068708 11 *
samux 1:80ab0d068708 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 1:80ab0d068708 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 1:80ab0d068708 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 1:80ab0d068708 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 1:80ab0d068708 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 1:80ab0d068708 17 */
samux 1:80ab0d068708 18
samux 1:80ab0d068708 19 #include "stdint.h"
samux 1:80ab0d068708 20 #include "USBMSD.h"
samux 1:80ab0d068708 21
samux 1:80ab0d068708 22 #define DISK_OK 0x00
samux 1:80ab0d068708 23 #define NO_INIT 0x01
samux 1:80ab0d068708 24 #define NO_DISK 0x02
samux 1:80ab0d068708 25 #define WRITE_PROTECT 0x04
samux 1:80ab0d068708 26
samux 1:80ab0d068708 27 #define CBW_Signature 0x43425355
samux 1:80ab0d068708 28 #define CSW_Signature 0x53425355
samux 1:80ab0d068708 29
samux 1:80ab0d068708 30 // SCSI Commands
samux 1:80ab0d068708 31 #define TEST_UNIT_READY 0x00
samux 1:80ab0d068708 32 #define REQUEST_SENSE 0x03
samux 1:80ab0d068708 33 #define FORMAT_UNIT 0x04
samux 1:80ab0d068708 34 #define INQUIRY 0x12
samux 1:80ab0d068708 35 #define MODE_SELECT6 0x15
samux 1:80ab0d068708 36 #define MODE_SENSE6 0x1A
samux 1:80ab0d068708 37 #define START_STOP_UNIT 0x1B
samux 1:80ab0d068708 38 #define MEDIA_REMOVAL 0x1E
samux 1:80ab0d068708 39 #define READ_FORMAT_CAPACITIES 0x23
samux 1:80ab0d068708 40 #define READ_CAPACITY 0x25
samux 1:80ab0d068708 41 #define READ10 0x28
samux 1:80ab0d068708 42 #define WRITE10 0x2A
samux 1:80ab0d068708 43 #define VERIFY10 0x2F
samux 1:80ab0d068708 44 #define READ12 0xA8
samux 1:80ab0d068708 45 #define WRITE12 0xAA
samux 1:80ab0d068708 46 #define MODE_SELECT10 0x55
samux 1:80ab0d068708 47 #define MODE_SENSE10 0x5A
samux 1:80ab0d068708 48
samux 1:80ab0d068708 49 // MSC class specific requests
samux 1:80ab0d068708 50 #define MSC_REQUEST_RESET 0xFF
samux 1:80ab0d068708 51 #define MSC_REQUEST_GET_MAX_LUN 0xFE
samux 1:80ab0d068708 52
samux 1:80ab0d068708 53 #define DEFAULT_CONFIGURATION (1)
samux 1:80ab0d068708 54
samux 1:80ab0d068708 55 // max packet size
samux 1:80ab0d068708 56 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK
samux 1:80ab0d068708 57
samux 1:80ab0d068708 58 // CSW Status
samux 1:80ab0d068708 59 enum Status {
samux 1:80ab0d068708 60 CSW_PASSED,
samux 1:80ab0d068708 61 CSW_FAILED,
samux 1:80ab0d068708 62 CSW_ERROR,
samux 1:80ab0d068708 63 };
samux 1:80ab0d068708 64
samux 1:80ab0d068708 65
samux 1:80ab0d068708 66 USBMSD::USBMSD(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
Patrickhalahan 72:e5c300b1df2f 67
Patrickhalahan 72:e5c300b1df2f 68
Patrickhalahan 72:e5c300b1df2f 69 extern int USBMSD_USBMSD_InstCount; // debug BL
Patrickhalahan 72:e5c300b1df2f 70 ++USBMSD_USBMSD_InstCount; // debug BL
Patrickhalahan 72:e5c300b1df2f 71
Patrickhalahan 72:e5c300b1df2f 72
samux 5:d27e4c226965 73 stage = READ_CBW;
samux 5:d27e4c226965 74 memset((void *)&cbw, 0, sizeof(CBW));
samux 5:d27e4c226965 75 memset((void *)&csw, 0, sizeof(CSW));
bogdanm 14:d495202c90f4 76 page = NULL;
samux 1:80ab0d068708 77 }
samux 1:80ab0d068708 78
bogdanm 14:d495202c90f4 79 USBMSD::~USBMSD() {
bogdanm 14:d495202c90f4 80 disconnect();
bogdanm 14:d495202c90f4 81 }
samux 1:80ab0d068708 82
samux 1:80ab0d068708 83
samux 1:80ab0d068708 84 // Called in ISR context to process a class specific request
samux 1:80ab0d068708 85 bool USBMSD::USBCallback_request(void) {
samux 1:80ab0d068708 86
samux 1:80ab0d068708 87 bool success = false;
samux 1:80ab0d068708 88 CONTROL_TRANSFER * transfer = getTransferPtr();
samux 1:80ab0d068708 89 static uint8_t maxLUN[1] = {0};
samux 1:80ab0d068708 90
samux 1:80ab0d068708 91 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
samux 1:80ab0d068708 92 switch (transfer->setup.bRequest) {
samux 1:80ab0d068708 93 case MSC_REQUEST_RESET:
samux 1:80ab0d068708 94 reset();
samux 1:80ab0d068708 95 success = true;
samux 1:80ab0d068708 96 break;
samux 1:80ab0d068708 97 case MSC_REQUEST_GET_MAX_LUN:
samux 1:80ab0d068708 98 transfer->remaining = 1;
samux 1:80ab0d068708 99 transfer->ptr = maxLUN;
samux 1:80ab0d068708 100 transfer->direction = DEVICE_TO_HOST;
samux 1:80ab0d068708 101 success = true;
samux 1:80ab0d068708 102 break;
samux 1:80ab0d068708 103 default:
samux 1:80ab0d068708 104 break;
samux 1:80ab0d068708 105 }
samux 1:80ab0d068708 106 }
samux 1:80ab0d068708 107
samux 1:80ab0d068708 108 return success;
samux 1:80ab0d068708 109 }
samux 1:80ab0d068708 110
samux 1:80ab0d068708 111
mbed_official 18:78bdbce94509 112 bool USBMSD::connect(bool blocking) {
Patrickhalahan 72:e5c300b1df2f 113 printf("USBMSD::connect\r\n");
samux 1:80ab0d068708 114 //disk initialization
samux 1:80ab0d068708 115 if (disk_status() & NO_INIT) {
samux 1:80ab0d068708 116 if (disk_initialize()) {
samux 1:80ab0d068708 117 return false;
samux 1:80ab0d068708 118 }
samux 1:80ab0d068708 119 }
samux 1:80ab0d068708 120
samux 1:80ab0d068708 121 // get number of blocks
samux 1:80ab0d068708 122 BlockCount = disk_sectors();
samux 1:80ab0d068708 123
samux 1:80ab0d068708 124 // get memory size
samux 1:80ab0d068708 125 MemorySize = disk_size();
samux 1:80ab0d068708 126
samux 7:f8f057664123 127 if (BlockCount > 0) {
samux 1:80ab0d068708 128 BlockSize = MemorySize / BlockCount;
samux 1:80ab0d068708 129 if (BlockSize != 0) {
bogdanm 14:d495202c90f4 130 free(page);
samux 1:80ab0d068708 131 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t));
samux 1:80ab0d068708 132 if (page == NULL)
samux 1:80ab0d068708 133 return false;
samux 1:80ab0d068708 134 }
samux 1:80ab0d068708 135 } else {
samux 1:80ab0d068708 136 return false;
samux 1:80ab0d068708 137 }
samux 1:80ab0d068708 138
samux 1:80ab0d068708 139 //connect the device
mbed_official 18:78bdbce94509 140 USBDevice::connect(blocking);
samux 1:80ab0d068708 141 return true;
samux 1:80ab0d068708 142 }
samux 1:80ab0d068708 143
bogdanm 14:d495202c90f4 144 void USBMSD::disconnect() {
mbed_official 51:deafa44182d9 145 USBDevice::disconnect();
bogdanm 14:d495202c90f4 146 //De-allocate MSD page size:
bogdanm 14:d495202c90f4 147 free(page);
bogdanm 14:d495202c90f4 148 page = NULL;
bogdanm 14:d495202c90f4 149 }
samux 1:80ab0d068708 150
samux 1:80ab0d068708 151 void USBMSD::reset() {
samux 1:80ab0d068708 152 stage = READ_CBW;
samux 1:80ab0d068708 153 }
samux 1:80ab0d068708 154
samux 1:80ab0d068708 155
samux 1:80ab0d068708 156 // Called in ISR context called when a data is received
mbed_official 47:a0cd9646ecd1 157 bool USBMSD::EPBULK_OUT_callback() {
samux 1:80ab0d068708 158 uint32_t size = 0;
samux 1:80ab0d068708 159 uint8_t buf[MAX_PACKET_SIZE_EPBULK];
samux 1:80ab0d068708 160 readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK);
samux 1:80ab0d068708 161 switch (stage) {
samux 1:80ab0d068708 162 // the device has to decode the CBW received
samux 1:80ab0d068708 163 case READ_CBW:
samux 1:80ab0d068708 164 CBWDecode(buf, size);
samux 1:80ab0d068708 165 break;
samux 1:80ab0d068708 166
samux 1:80ab0d068708 167 // the device has to receive data from the host
samux 1:80ab0d068708 168 case PROCESS_CBW:
samux 1:80ab0d068708 169 switch (cbw.CB[0]) {
samux 1:80ab0d068708 170 case WRITE10:
samux 1:80ab0d068708 171 case WRITE12:
samux 1:80ab0d068708 172 memoryWrite(buf, size);
samux 1:80ab0d068708 173 break;
samux 1:80ab0d068708 174 case VERIFY10:
samux 1:80ab0d068708 175 memoryVerify(buf, size);
samux 1:80ab0d068708 176 break;
samux 1:80ab0d068708 177 }
samux 1:80ab0d068708 178 break;
samux 1:80ab0d068708 179
samux 1:80ab0d068708 180 // an error has occured: stall endpoint and send CSW
samux 1:80ab0d068708 181 default:
samux 1:80ab0d068708 182 stallEndpoint(EPBULK_OUT);
samux 1:80ab0d068708 183 csw.Status = CSW_ERROR;
samux 1:80ab0d068708 184 sendCSW();
samux 1:80ab0d068708 185 break;
samux 1:80ab0d068708 186 }
samux 1:80ab0d068708 187
samux 1:80ab0d068708 188 //reactivate readings on the OUT bulk endpoint
samux 1:80ab0d068708 189 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
samux 1:80ab0d068708 190 return true;
samux 1:80ab0d068708 191 }
samux 1:80ab0d068708 192
samux 1:80ab0d068708 193 // Called in ISR context when a data has been transferred
mbed_official 47:a0cd9646ecd1 194 bool USBMSD::EPBULK_IN_callback() {
samux 1:80ab0d068708 195 switch (stage) {
samux 1:80ab0d068708 196
samux 1:80ab0d068708 197 // the device has to send data to the host
samux 1:80ab0d068708 198 case PROCESS_CBW:
samux 1:80ab0d068708 199 switch (cbw.CB[0]) {
samux 1:80ab0d068708 200 case READ10:
samux 1:80ab0d068708 201 case READ12:
samux 1:80ab0d068708 202 memoryRead();
samux 1:80ab0d068708 203 break;
samux 1:80ab0d068708 204 }
samux 1:80ab0d068708 205 break;
samux 1:80ab0d068708 206
samux 1:80ab0d068708 207 //the device has to send a CSW
samux 1:80ab0d068708 208 case SEND_CSW:
samux 1:80ab0d068708 209 sendCSW();
samux 1:80ab0d068708 210 break;
samux 1:80ab0d068708 211
bogdanm 11:eeb3cbbaa996 212 // the host has received the CSW -> we wait a CBW
bogdanm 11:eeb3cbbaa996 213 case WAIT_CSW:
bogdanm 11:eeb3cbbaa996 214 stage = READ_CBW;
bogdanm 11:eeb3cbbaa996 215 break;
bogdanm 11:eeb3cbbaa996 216
bogdanm 11:eeb3cbbaa996 217 // an error has occured
bogdanm 11:eeb3cbbaa996 218 default:
samux 1:80ab0d068708 219 stallEndpoint(EPBULK_IN);
samux 1:80ab0d068708 220 sendCSW();
samux 1:80ab0d068708 221 break;
samux 1:80ab0d068708 222 }
samux 1:80ab0d068708 223 return true;
samux 1:80ab0d068708 224 }
samux 1:80ab0d068708 225
samux 1:80ab0d068708 226
samux 1:80ab0d068708 227 void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) {
samux 1:80ab0d068708 228
samux 1:80ab0d068708 229 if ((addr + size) > MemorySize) {
samux 1:80ab0d068708 230 size = MemorySize - addr;
samux 1:80ab0d068708 231 stage = ERROR;
samux 1:80ab0d068708 232 stallEndpoint(EPBULK_OUT);
samux 1:80ab0d068708 233 }
samux 1:80ab0d068708 234
samux 1:80ab0d068708 235 // we fill an array in RAM of 1 block before writing it in memory
samux 1:80ab0d068708 236 for (int i = 0; i < size; i++)
samux 1:80ab0d068708 237 page[addr%BlockSize + i] = buf[i];
samux 1:80ab0d068708 238
samux 1:80ab0d068708 239 // if the array is filled, write it in memory
samux 1:80ab0d068708 240 if (!((addr + size)%BlockSize)) {
samux 1:80ab0d068708 241 if (!(disk_status() & WRITE_PROTECT)) {
mbed_official 29:b7a0ea455a0c 242 disk_write(page, addr/BlockSize, 1);
samux 1:80ab0d068708 243 }
samux 1:80ab0d068708 244 }
samux 1:80ab0d068708 245
samux 1:80ab0d068708 246 addr += size;
samux 1:80ab0d068708 247 length -= size;
samux 1:80ab0d068708 248 csw.DataResidue -= size;
samux 1:80ab0d068708 249
samux 1:80ab0d068708 250 if ((!length) || (stage != PROCESS_CBW)) {
samux 1:80ab0d068708 251 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED;
samux 1:80ab0d068708 252 sendCSW();
samux 1:80ab0d068708 253 }
samux 1:80ab0d068708 254 }
samux 1:80ab0d068708 255
samux 1:80ab0d068708 256 void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) {
samux 1:80ab0d068708 257 uint32_t n;
samux 1:80ab0d068708 258
samux 1:80ab0d068708 259 if ((addr + size) > MemorySize) {
samux 1:80ab0d068708 260 size = MemorySize - addr;
samux 1:80ab0d068708 261 stage = ERROR;
samux 1:80ab0d068708 262 stallEndpoint(EPBULK_OUT);
samux 1:80ab0d068708 263 }
samux 1:80ab0d068708 264
samux 1:80ab0d068708 265 // beginning of a new block -> load a whole block in RAM
samux 1:80ab0d068708 266 if (!(addr%BlockSize))
mbed_official 29:b7a0ea455a0c 267 disk_read(page, addr/BlockSize, 1);
samux 1:80ab0d068708 268
samux 1:80ab0d068708 269 // info are in RAM -> no need to re-read memory
samux 1:80ab0d068708 270 for (n = 0; n < size; n++) {
samux 1:80ab0d068708 271 if (page[addr%BlockSize + n] != buf[n]) {
samux 1:80ab0d068708 272 memOK = false;
samux 1:80ab0d068708 273 break;
samux 1:80ab0d068708 274 }
samux 1:80ab0d068708 275 }
samux 1:80ab0d068708 276
samux 1:80ab0d068708 277 addr += size;
samux 1:80ab0d068708 278 length -= size;
samux 1:80ab0d068708 279 csw.DataResidue -= size;
samux 1:80ab0d068708 280
samux 1:80ab0d068708 281 if ( !length || (stage != PROCESS_CBW)) {
samux 1:80ab0d068708 282 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED;
samux 1:80ab0d068708 283 sendCSW();
samux 1:80ab0d068708 284 }
samux 1:80ab0d068708 285 }
samux 1:80ab0d068708 286
samux 1:80ab0d068708 287
samux 1:80ab0d068708 288 bool USBMSD::inquiryRequest (void) {
samux 1:80ab0d068708 289 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01,
samux 1:80ab0d068708 290 36 - 4, 0x80, 0x00, 0x00,
samux 1:80ab0d068708 291 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G',
samux 1:80ab0d068708 292 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ',
samux 1:80ab0d068708 293 '1', '.', '0', ' ',
samux 1:80ab0d068708 294 };
samux 1:80ab0d068708 295 if (!write(inquiry, sizeof(inquiry))) {
samux 1:80ab0d068708 296 return false;
samux 1:80ab0d068708 297 }
samux 1:80ab0d068708 298 return true;
samux 1:80ab0d068708 299 }
samux 1:80ab0d068708 300
samux 1:80ab0d068708 301
samux 1:80ab0d068708 302 bool USBMSD::readFormatCapacity() {
samux 1:80ab0d068708 303 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08,
bogdanm 11:eeb3cbbaa996 304 (uint8_t)((BlockCount >> 24) & 0xff),
bogdanm 11:eeb3cbbaa996 305 (uint8_t)((BlockCount >> 16) & 0xff),
bogdanm 11:eeb3cbbaa996 306 (uint8_t)((BlockCount >> 8) & 0xff),
bogdanm 11:eeb3cbbaa996 307 (uint8_t)((BlockCount >> 0) & 0xff),
samux 1:80ab0d068708 308
samux 1:80ab0d068708 309 0x02,
bogdanm 11:eeb3cbbaa996 310 (uint8_t)((BlockSize >> 16) & 0xff),
bogdanm 11:eeb3cbbaa996 311 (uint8_t)((BlockSize >> 8) & 0xff),
bogdanm 11:eeb3cbbaa996 312 (uint8_t)((BlockSize >> 0) & 0xff),
samux 1:80ab0d068708 313 };
samux 1:80ab0d068708 314 if (!write(capacity, sizeof(capacity))) {
samux 1:80ab0d068708 315 return false;
samux 1:80ab0d068708 316 }
samux 1:80ab0d068708 317 return true;
samux 1:80ab0d068708 318 }
samux 1:80ab0d068708 319
samux 1:80ab0d068708 320
samux 1:80ab0d068708 321 bool USBMSD::readCapacity (void) {
samux 1:80ab0d068708 322 uint8_t capacity[] = {
bogdanm 11:eeb3cbbaa996 323 (uint8_t)(((BlockCount - 1) >> 24) & 0xff),
bogdanm 11:eeb3cbbaa996 324 (uint8_t)(((BlockCount - 1) >> 16) & 0xff),
bogdanm 11:eeb3cbbaa996 325 (uint8_t)(((BlockCount - 1) >> 8) & 0xff),
bogdanm 11:eeb3cbbaa996 326 (uint8_t)(((BlockCount - 1) >> 0) & 0xff),
samux 1:80ab0d068708 327
bogdanm 11:eeb3cbbaa996 328 (uint8_t)((BlockSize >> 24) & 0xff),
bogdanm 11:eeb3cbbaa996 329 (uint8_t)((BlockSize >> 16) & 0xff),
bogdanm 11:eeb3cbbaa996 330 (uint8_t)((BlockSize >> 8) & 0xff),
bogdanm 11:eeb3cbbaa996 331 (uint8_t)((BlockSize >> 0) & 0xff),
samux 1:80ab0d068708 332 };
samux 1:80ab0d068708 333 if (!write(capacity, sizeof(capacity))) {
samux 1:80ab0d068708 334 return false;
samux 1:80ab0d068708 335 }
samux 1:80ab0d068708 336 return true;
samux 1:80ab0d068708 337 }
samux 1:80ab0d068708 338
samux 1:80ab0d068708 339 bool USBMSD::write (uint8_t * buf, uint16_t size) {
samux 1:80ab0d068708 340
samux 1:80ab0d068708 341 if (size >= cbw.DataLength) {
samux 1:80ab0d068708 342 size = cbw.DataLength;
samux 1:80ab0d068708 343 }
samux 1:80ab0d068708 344 stage = SEND_CSW;
samux 1:80ab0d068708 345
samux 1:80ab0d068708 346 if (!writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) {
samux 1:80ab0d068708 347 return false;
samux 1:80ab0d068708 348 }
samux 1:80ab0d068708 349
samux 1:80ab0d068708 350 csw.DataResidue -= size;
samux 1:80ab0d068708 351 csw.Status = CSW_PASSED;
samux 1:80ab0d068708 352 return true;
samux 1:80ab0d068708 353 }
samux 1:80ab0d068708 354
samux 1:80ab0d068708 355
samux 1:80ab0d068708 356 bool USBMSD::modeSense6 (void) {
samux 1:80ab0d068708 357 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 };
samux 1:80ab0d068708 358 if (!write(sense6, sizeof(sense6))) {
samux 1:80ab0d068708 359 return false;
samux 1:80ab0d068708 360 }
samux 1:80ab0d068708 361 return true;
samux 1:80ab0d068708 362 }
samux 1:80ab0d068708 363
samux 1:80ab0d068708 364 void USBMSD::sendCSW() {
samux 1:80ab0d068708 365 csw.Signature = CSW_Signature;
samux 1:80ab0d068708 366 writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK);
samux 1:80ab0d068708 367 stage = WAIT_CSW;
samux 1:80ab0d068708 368 }
samux 1:80ab0d068708 369
samux 1:80ab0d068708 370 bool USBMSD::requestSense (void) {
samux 1:80ab0d068708 371 uint8_t request_sense[] = {
samux 1:80ab0d068708 372 0x70,
samux 1:80ab0d068708 373 0x00,
samux 1:80ab0d068708 374 0x05, // Sense Key: illegal request
samux 1:80ab0d068708 375 0x00,
samux 1:80ab0d068708 376 0x00,
samux 1:80ab0d068708 377 0x00,
samux 1:80ab0d068708 378 0x00,
samux 1:80ab0d068708 379 0x0A,
samux 1:80ab0d068708 380 0x00,
samux 1:80ab0d068708 381 0x00,
samux 1:80ab0d068708 382 0x00,
samux 1:80ab0d068708 383 0x00,
samux 1:80ab0d068708 384 0x30,
samux 1:80ab0d068708 385 0x01,
samux 1:80ab0d068708 386 0x00,
samux 1:80ab0d068708 387 0x00,
samux 1:80ab0d068708 388 0x00,
samux 1:80ab0d068708 389 0x00,
samux 1:80ab0d068708 390 };
samux 1:80ab0d068708 391
samux 1:80ab0d068708 392 if (!write(request_sense, sizeof(request_sense))) {
samux 1:80ab0d068708 393 return false;
samux 1:80ab0d068708 394 }
samux 1:80ab0d068708 395
samux 1:80ab0d068708 396 return true;
samux 1:80ab0d068708 397 }
samux 1:80ab0d068708 398
samux 1:80ab0d068708 399 void USBMSD::fail() {
samux 1:80ab0d068708 400 csw.Status = CSW_FAILED;
samux 1:80ab0d068708 401 sendCSW();
samux 1:80ab0d068708 402 }
samux 1:80ab0d068708 403
samux 1:80ab0d068708 404
samux 1:80ab0d068708 405 void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) {
samux 1:80ab0d068708 406 if (size == sizeof(cbw)) {
samux 1:80ab0d068708 407 memcpy((uint8_t *)&cbw, buf, size);
samux 1:80ab0d068708 408 if (cbw.Signature == CBW_Signature) {
samux 1:80ab0d068708 409 csw.Tag = cbw.Tag;
samux 1:80ab0d068708 410 csw.DataResidue = cbw.DataLength;
samux 1:80ab0d068708 411 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) {
samux 1:80ab0d068708 412 fail();
samux 1:80ab0d068708 413 } else {
samux 1:80ab0d068708 414 switch (cbw.CB[0]) {
samux 1:80ab0d068708 415 case TEST_UNIT_READY:
samux 1:80ab0d068708 416 testUnitReady();
samux 1:80ab0d068708 417 break;
samux 1:80ab0d068708 418 case REQUEST_SENSE:
samux 1:80ab0d068708 419 requestSense();
samux 1:80ab0d068708 420 break;
samux 1:80ab0d068708 421 case INQUIRY:
samux 1:80ab0d068708 422 inquiryRequest();
samux 1:80ab0d068708 423 break;
samux 1:80ab0d068708 424 case MODE_SENSE6:
samux 1:80ab0d068708 425 modeSense6();
samux 1:80ab0d068708 426 break;
samux 1:80ab0d068708 427 case READ_FORMAT_CAPACITIES:
samux 1:80ab0d068708 428 readFormatCapacity();
samux 1:80ab0d068708 429 break;
samux 1:80ab0d068708 430 case READ_CAPACITY:
samux 1:80ab0d068708 431 readCapacity();
samux 1:80ab0d068708 432 break;
samux 1:80ab0d068708 433 case READ10:
samux 1:80ab0d068708 434 case READ12:
samux 1:80ab0d068708 435 if (infoTransfer()) {
samux 1:80ab0d068708 436 if ((cbw.Flags & 0x80)) {
samux 1:80ab0d068708 437 stage = PROCESS_CBW;
samux 1:80ab0d068708 438 memoryRead();
samux 1:80ab0d068708 439 } else {
samux 1:80ab0d068708 440 stallEndpoint(EPBULK_OUT);
samux 1:80ab0d068708 441 csw.Status = CSW_ERROR;
samux 1:80ab0d068708 442 sendCSW();
samux 1:80ab0d068708 443 }
samux 1:80ab0d068708 444 }
samux 1:80ab0d068708 445 break;
samux 1:80ab0d068708 446 case WRITE10:
samux 1:80ab0d068708 447 case WRITE12:
samux 1:80ab0d068708 448 if (infoTransfer()) {
samux 1:80ab0d068708 449 if (!(cbw.Flags & 0x80)) {
samux 1:80ab0d068708 450 stage = PROCESS_CBW;
samux 1:80ab0d068708 451 } else {
samux 1:80ab0d068708 452 stallEndpoint(EPBULK_IN);
samux 1:80ab0d068708 453 csw.Status = CSW_ERROR;
samux 1:80ab0d068708 454 sendCSW();
samux 1:80ab0d068708 455 }
samux 1:80ab0d068708 456 }
samux 1:80ab0d068708 457 break;
samux 1:80ab0d068708 458 case VERIFY10:
samux 1:80ab0d068708 459 if (!(cbw.CB[1] & 0x02)) {
samux 1:80ab0d068708 460 csw.Status = CSW_PASSED;
samux 1:80ab0d068708 461 sendCSW();
samux 1:80ab0d068708 462 break;
samux 1:80ab0d068708 463 }
samux 1:80ab0d068708 464 if (infoTransfer()) {
samux 1:80ab0d068708 465 if (!(cbw.Flags & 0x80)) {
samux 1:80ab0d068708 466 stage = PROCESS_CBW;
samux 1:80ab0d068708 467 memOK = true;
samux 1:80ab0d068708 468 } else {
samux 1:80ab0d068708 469 stallEndpoint(EPBULK_IN);
samux 1:80ab0d068708 470 csw.Status = CSW_ERROR;
samux 1:80ab0d068708 471 sendCSW();
samux 1:80ab0d068708 472 }
samux 1:80ab0d068708 473 }
samux 1:80ab0d068708 474 break;
samux 3:6d85e04fb59f 475 case MEDIA_REMOVAL:
samux 3:6d85e04fb59f 476 csw.Status = CSW_PASSED;
samux 3:6d85e04fb59f 477 sendCSW();
samux 3:6d85e04fb59f 478 break;
samux 1:80ab0d068708 479 default:
samux 1:80ab0d068708 480 fail();
samux 1:80ab0d068708 481 break;
samux 1:80ab0d068708 482 }
samux 1:80ab0d068708 483 }
samux 1:80ab0d068708 484 }
samux 1:80ab0d068708 485 }
samux 1:80ab0d068708 486 }
samux 1:80ab0d068708 487
samux 1:80ab0d068708 488 void USBMSD::testUnitReady (void) {
samux 1:80ab0d068708 489
samux 1:80ab0d068708 490 if (cbw.DataLength != 0) {
samux 1:80ab0d068708 491 if ((cbw.Flags & 0x80) != 0) {
samux 1:80ab0d068708 492 stallEndpoint(EPBULK_IN);
samux 1:80ab0d068708 493 } else {
samux 1:80ab0d068708 494 stallEndpoint(EPBULK_OUT);
samux 1:80ab0d068708 495 }
samux 1:80ab0d068708 496 }
samux 1:80ab0d068708 497
samux 1:80ab0d068708 498 csw.Status = CSW_PASSED;
samux 1:80ab0d068708 499 sendCSW();
samux 1:80ab0d068708 500 }
samux 1:80ab0d068708 501
samux 1:80ab0d068708 502
samux 1:80ab0d068708 503 void USBMSD::memoryRead (void) {
samux 1:80ab0d068708 504 uint32_t n;
samux 1:80ab0d068708 505
samux 1:80ab0d068708 506 n = (length > MAX_PACKET) ? MAX_PACKET : length;
samux 1:80ab0d068708 507
samux 1:80ab0d068708 508 if ((addr + n) > MemorySize) {
samux 1:80ab0d068708 509 n = MemorySize - addr;
samux 1:80ab0d068708 510 stage = ERROR;
samux 1:80ab0d068708 511 }
samux 1:80ab0d068708 512
samux 1:80ab0d068708 513 // we read an entire block
samux 1:80ab0d068708 514 if (!(addr%BlockSize))
mbed_official 29:b7a0ea455a0c 515 disk_read(page, addr/BlockSize, 1);
samux 1:80ab0d068708 516
samux 1:80ab0d068708 517 // write data which are in RAM
samux 1:80ab0d068708 518 writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK);
samux 1:80ab0d068708 519
samux 1:80ab0d068708 520 addr += n;
samux 1:80ab0d068708 521 length -= n;
samux 1:80ab0d068708 522
samux 1:80ab0d068708 523 csw.DataResidue -= n;
samux 1:80ab0d068708 524
samux 1:80ab0d068708 525 if ( !length || (stage != PROCESS_CBW)) {
samux 1:80ab0d068708 526 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
samux 1:80ab0d068708 527 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage;
samux 1:80ab0d068708 528 }
samux 1:80ab0d068708 529 }
samux 1:80ab0d068708 530
samux 1:80ab0d068708 531
samux 1:80ab0d068708 532 bool USBMSD::infoTransfer (void) {
samux 1:80ab0d068708 533 uint32_t n;
samux 1:80ab0d068708 534
samux 1:80ab0d068708 535 // Logical Block Address of First Block
samux 1:80ab0d068708 536 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0);
samux 1:80ab0d068708 537
samux 1:80ab0d068708 538 addr = n * BlockSize;
samux 1:80ab0d068708 539
samux 1:80ab0d068708 540 // Number of Blocks to transfer
samux 1:80ab0d068708 541 switch (cbw.CB[0]) {
samux 1:80ab0d068708 542 case READ10:
samux 1:80ab0d068708 543 case WRITE10:
samux 1:80ab0d068708 544 case VERIFY10:
samux 1:80ab0d068708 545 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0);
samux 1:80ab0d068708 546 break;
samux 1:80ab0d068708 547
samux 1:80ab0d068708 548 case READ12:
samux 1:80ab0d068708 549 case WRITE12:
samux 1:80ab0d068708 550 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0);
samux 1:80ab0d068708 551 break;
samux 1:80ab0d068708 552 }
samux 1:80ab0d068708 553
samux 1:80ab0d068708 554 length = n * BlockSize;
samux 1:80ab0d068708 555
samux 1:80ab0d068708 556 if (!cbw.DataLength) { // host requests no data
samux 1:80ab0d068708 557 csw.Status = CSW_FAILED;
samux 1:80ab0d068708 558 sendCSW();
samux 1:80ab0d068708 559 return false;
samux 1:80ab0d068708 560 }
samux 1:80ab0d068708 561
samux 1:80ab0d068708 562 if (cbw.DataLength != length) {
samux 1:80ab0d068708 563 if ((cbw.Flags & 0x80) != 0) {
samux 1:80ab0d068708 564 stallEndpoint(EPBULK_IN);
samux 1:80ab0d068708 565 } else {
samux 1:80ab0d068708 566 stallEndpoint(EPBULK_OUT);
samux 1:80ab0d068708 567 }
samux 1:80ab0d068708 568
samux 1:80ab0d068708 569 csw.Status = CSW_FAILED;
samux 1:80ab0d068708 570 sendCSW();
samux 1:80ab0d068708 571 return false;
samux 1:80ab0d068708 572 }
samux 1:80ab0d068708 573
samux 1:80ab0d068708 574 return true;
samux 1:80ab0d068708 575 }
samux 1:80ab0d068708 576
samux 1:80ab0d068708 577
samux 1:80ab0d068708 578
samux 1:80ab0d068708 579
samux 1:80ab0d068708 580
samux 1:80ab0d068708 581 // Called in ISR context
samux 1:80ab0d068708 582 // Set configuration. Return false if the
samux 1:80ab0d068708 583 // configuration is not supported.
samux 1:80ab0d068708 584 bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) {
samux 1:80ab0d068708 585 if (configuration != DEFAULT_CONFIGURATION) {
samux 1:80ab0d068708 586 return false;
samux 1:80ab0d068708 587 }
samux 1:80ab0d068708 588
samux 1:80ab0d068708 589 // Configure endpoints > 0
samux 1:80ab0d068708 590 addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
samux 1:80ab0d068708 591 addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
samux 1:80ab0d068708 592
samux 1:80ab0d068708 593 //activate readings
samux 1:80ab0d068708 594 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
samux 1:80ab0d068708 595 return true;
samux 1:80ab0d068708 596 }
samux 1:80ab0d068708 597
samux 1:80ab0d068708 598
samux 1:80ab0d068708 599 uint8_t * USBMSD::stringIinterfaceDesc() {
samux 1:80ab0d068708 600 static uint8_t stringIinterfaceDescriptor[] = {
samux 1:80ab0d068708 601 0x08, //bLength
samux 1:80ab0d068708 602 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 1:80ab0d068708 603 'M',0,'S',0,'D',0 //bString iInterface - MSD
samux 1:80ab0d068708 604 };
samux 1:80ab0d068708 605 return stringIinterfaceDescriptor;
samux 1:80ab0d068708 606 }
samux 1:80ab0d068708 607
samux 1:80ab0d068708 608 uint8_t * USBMSD::stringIproductDesc() {
samux 1:80ab0d068708 609 static uint8_t stringIproductDescriptor[] = {
samux 1:80ab0d068708 610 0x12, //bLength
samux 1:80ab0d068708 611 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 1:80ab0d068708 612 'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio
samux 1:80ab0d068708 613 };
samux 1:80ab0d068708 614 return stringIproductDescriptor;
samux 1:80ab0d068708 615 }
samux 1:80ab0d068708 616
samux 1:80ab0d068708 617
samux 1:80ab0d068708 618 uint8_t * USBMSD::configurationDesc() {
samux 1:80ab0d068708 619 static uint8_t configDescriptor[] = {
samux 1:80ab0d068708 620
samux 1:80ab0d068708 621 // Configuration 1
samux 1:80ab0d068708 622 9, // bLength
samux 1:80ab0d068708 623 2, // bDescriptorType
samux 1:80ab0d068708 624 LSB(9 + 9 + 7 + 7), // wTotalLength
samux 1:80ab0d068708 625 MSB(9 + 9 + 7 + 7),
samux 1:80ab0d068708 626 0x01, // bNumInterfaces
samux 1:80ab0d068708 627 0x01, // bConfigurationValue: 0x01 is used to select this configuration
samux 1:80ab0d068708 628 0x00, // iConfiguration: no string to describe this configuration
samux 1:80ab0d068708 629 0xC0, // bmAttributes
samux 1:80ab0d068708 630 100, // bMaxPower, device power consumption is 100 mA
samux 1:80ab0d068708 631
samux 1:80ab0d068708 632 // Interface 0, Alternate Setting 0, MSC Class
samux 1:80ab0d068708 633 9, // bLength
samux 1:80ab0d068708 634 4, // bDescriptorType
samux 1:80ab0d068708 635 0x00, // bInterfaceNumber
samux 1:80ab0d068708 636 0x00, // bAlternateSetting
samux 1:80ab0d068708 637 0x02, // bNumEndpoints
samux 1:80ab0d068708 638 0x08, // bInterfaceClass
samux 1:80ab0d068708 639 0x06, // bInterfaceSubClass
samux 1:80ab0d068708 640 0x50, // bInterfaceProtocol
samux 1:80ab0d068708 641 0x04, // iInterface
samux 1:80ab0d068708 642
samux 1:80ab0d068708 643 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
samux 1:80ab0d068708 644 7, // bLength
samux 1:80ab0d068708 645 5, // bDescriptorType
samux 1:80ab0d068708 646 PHY_TO_DESC(EPBULK_IN), // bEndpointAddress
samux 1:80ab0d068708 647 0x02, // bmAttributes (0x02=bulk)
samux 1:80ab0d068708 648 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
samux 1:80ab0d068708 649 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
samux 1:80ab0d068708 650 0, // bInterval
samux 1:80ab0d068708 651
samux 1:80ab0d068708 652 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
samux 1:80ab0d068708 653 7, // bLength
samux 1:80ab0d068708 654 5, // bDescriptorType
samux 1:80ab0d068708 655 PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress
samux 1:80ab0d068708 656 0x02, // bmAttributes (0x02=bulk)
samux 1:80ab0d068708 657 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
samux 1:80ab0d068708 658 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
samux 1:80ab0d068708 659 0 // bInterval
samux 1:80ab0d068708 660 };
samux 1:80ab0d068708 661 return configDescriptor;
samux 8:335f2506f422 662 }