USB composite device example program, drag-and-drop flash writer.

Dependencies:   SWD USBDevice mbed BaseDAP

Committer:
va009039
Date:
Sat Sep 28 03:21:14 2013 +0000
Revision:
1:ea8e179320d7
add USBMSD_Drop class. add CDC(Virtual COM) and HID(for example CMSIS-DAP), but KL25Z not work.

Who changed what in which revision?

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