USBMSD test for GR-PEACH

Dependencies:   USBDevice USBMSD_SD mbed

Fork of USBMSD_SD_HelloWorld_Mbed by Samuel Mokrani

Committer:
samux
Date:
Wed Nov 16 17:17:42 2011 +0000
Revision:
11:a26e7b7a1221
Parent:
10:cf8fd2b6ca23
Child:
12:a12eb1fc05f3
GOOD COMMIT: msd and hid work even on MAC...

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 7:6494da2a5c60 1 // USBMSD.cpp
samux 7:6494da2a5c60 2 // USB mass storage device example
samux 7:6494da2a5c60 3 // Copyright (c) 2011 ARM Limited. All rights reserved.
samux 7:6494da2a5c60 4
samux 7:6494da2a5c60 5 #include "stdint.h"
samux 7:6494da2a5c60 6 #include "USBMSD.h"
samux 7:6494da2a5c60 7 #include "USBBusInterface.h"
samux 7:6494da2a5c60 8
samux 7:6494da2a5c60 9 #define CBW_Signature 0x43425355
samux 7:6494da2a5c60 10 #define CSW_Signature 0x53425355
samux 7:6494da2a5c60 11
samux 7:6494da2a5c60 12 // SCSI Commands
samux 7:6494da2a5c60 13 #define TEST_UNIT_READY 0x00
samux 7:6494da2a5c60 14 #define REQUEST_SENSE 0x03
samux 7:6494da2a5c60 15 #define FORMAT_UNIT 0x04
samux 7:6494da2a5c60 16 #define INQUIRY 0x12
samux 7:6494da2a5c60 17 #define MODE_SELECT6 0x15
samux 7:6494da2a5c60 18 #define MODE_SENSE6 0x1A
samux 7:6494da2a5c60 19 #define START_STOP_UNIT 0x1B
samux 7:6494da2a5c60 20 #define MEDIA_REMOVAL 0x1E
samux 7:6494da2a5c60 21 #define READ_FORMAT_CAPACITIES 0x23
samux 7:6494da2a5c60 22 #define READ_CAPACITY 0x25
samux 7:6494da2a5c60 23 #define READ10 0x28
samux 7:6494da2a5c60 24 #define WRITE10 0x2A
samux 7:6494da2a5c60 25 #define VERIFY10 0x2F
samux 7:6494da2a5c60 26 #define READ12 0xA8
samux 7:6494da2a5c60 27 #define WRITE12 0xAA
samux 7:6494da2a5c60 28 #define MODE_SELECT10 0x55
samux 7:6494da2a5c60 29 #define MODE_SENSE10 0x5A
samux 7:6494da2a5c60 30
samux 7:6494da2a5c60 31 // MSC class specific requests
samux 7:6494da2a5c60 32 #define MSC_REQUEST_RESET 0xFF
samux 7:6494da2a5c60 33 #define MSC_REQUEST_GET_MAX_LUN 0xFE
samux 7:6494da2a5c60 34
samux 7:6494da2a5c60 35 #define DEFAULT_CONFIGURATION (1)
samux 7:6494da2a5c60 36
samux 7:6494da2a5c60 37 // Max In/Out Packet Size on the bulk endpoint */
samux 7:6494da2a5c60 38 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK
samux 7:6494da2a5c60 39
samux 7:6494da2a5c60 40 // CSW Status
samux 7:6494da2a5c60 41 enum Status {
samux 7:6494da2a5c60 42 CSW_PASSED,
samux 7:6494da2a5c60 43 CSW_FAILED,
samux 7:6494da2a5c60 44 CSW_ERROR,
samux 7:6494da2a5c60 45 };
samux 7:6494da2a5c60 46
samux 7:6494da2a5c60 47
samux 7:6494da2a5c60 48 USBMSD::USBMSD(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
samux 7:6494da2a5c60 49 }
samux 7:6494da2a5c60 50
samux 10:cf8fd2b6ca23 51 bool USBMSD::USBCallback_request() {
samux 7:6494da2a5c60 52 bool success = false;
samux 7:6494da2a5c60 53 CONTROL_TRANSFER * transfer = getTransferPtr();
samux 10:cf8fd2b6ca23 54 uint8_t *hidDescriptor;
samux 10:cf8fd2b6ca23 55
samux 10:cf8fd2b6ca23 56 // Process additional standard requests
samux 10:cf8fd2b6ca23 57
samux 10:cf8fd2b6ca23 58 if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE)) {
samux 10:cf8fd2b6ca23 59 switch (transfer->setup.bRequest) {
samux 10:cf8fd2b6ca23 60 case GET_DESCRIPTOR:
samux 10:cf8fd2b6ca23 61 switch (DESCRIPTOR_TYPE(transfer->setup.wValue)) {
samux 10:cf8fd2b6ca23 62 case REPORT_DESCRIPTOR:
samux 10:cf8fd2b6ca23 63 if ((reportDesc() != NULL) \
samux 10:cf8fd2b6ca23 64 && (reportDescLength() != 0)) {
samux 10:cf8fd2b6ca23 65 transfer->remaining = reportDescLength();
samux 10:cf8fd2b6ca23 66 transfer->ptr = reportDesc();
samux 10:cf8fd2b6ca23 67 transfer->direction = DEVICE_TO_HOST;
samux 10:cf8fd2b6ca23 68 success = true;
samux 10:cf8fd2b6ca23 69 }
samux 10:cf8fd2b6ca23 70 break;
samux 10:cf8fd2b6ca23 71 case HID_DESCRIPTOR:
samux 10:cf8fd2b6ca23 72 // Find the HID descriptor, after the configuration descriptor
samux 10:cf8fd2b6ca23 73 hidDescriptor = findDescriptor(HID_DESCRIPTOR);
samux 10:cf8fd2b6ca23 74 if (hidDescriptor != NULL) {
samux 10:cf8fd2b6ca23 75 transfer->remaining = HID_DESCRIPTOR_LENGTH;
samux 10:cf8fd2b6ca23 76 transfer->ptr = hidDescriptor;
samux 10:cf8fd2b6ca23 77 transfer->direction = DEVICE_TO_HOST;
samux 10:cf8fd2b6ca23 78 success = true;
samux 10:cf8fd2b6ca23 79 }
samux 10:cf8fd2b6ca23 80 break;
samux 10:cf8fd2b6ca23 81
samux 10:cf8fd2b6ca23 82 default:
samux 10:cf8fd2b6ca23 83 break;
samux 10:cf8fd2b6ca23 84 }
samux 10:cf8fd2b6ca23 85 break;
samux 10:cf8fd2b6ca23 86 default:
samux 10:cf8fd2b6ca23 87 break;
samux 10:cf8fd2b6ca23 88 }
samux 10:cf8fd2b6ca23 89 }
samux 10:cf8fd2b6ca23 90
samux 10:cf8fd2b6ca23 91 // Process class-specific requests
samux 7:6494da2a5c60 92
samux 7:6494da2a5c60 93 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
samux 10:cf8fd2b6ca23 94 uint8_t * dum = {0};
samux 7:6494da2a5c60 95 switch (transfer->setup.bRequest) {
samux 10:cf8fd2b6ca23 96 case SET_REPORT:
samux 10:cf8fd2b6ca23 97 // First byte will be used for report ID
samux 10:cf8fd2b6ca23 98 outputReport.data[0] = transfer->setup.wValue & 0xff;
samux 10:cf8fd2b6ca23 99 outputReport.length = transfer->setup.wLength + 1;
samux 10:cf8fd2b6ca23 100
samux 10:cf8fd2b6ca23 101 transfer->remaining = sizeof(outputReport.data) - 1;
samux 10:cf8fd2b6ca23 102 transfer->ptr = &outputReport.data[1];
samux 10:cf8fd2b6ca23 103 transfer->direction = HOST_TO_DEVICE;
samux 10:cf8fd2b6ca23 104 transfer->notify = true;
samux 7:6494da2a5c60 105 success = true;
samux 7:6494da2a5c60 106 case MSC_REQUEST_GET_MAX_LUN:
samux 7:6494da2a5c60 107 transfer->remaining = 1;
samux 10:cf8fd2b6ca23 108 transfer->ptr = dum;
samux 7:6494da2a5c60 109 transfer->direction = DEVICE_TO_HOST;
samux 7:6494da2a5c60 110 success = true;
samux 7:6494da2a5c60 111 break;
samux 10:cf8fd2b6ca23 112 case SET_IDLE:
samux 10:cf8fd2b6ca23 113 success = true;
samux 7:6494da2a5c60 114 default:
samux 7:6494da2a5c60 115 break;
samux 7:6494da2a5c60 116 }
samux 7:6494da2a5c60 117 }
samux 7:6494da2a5c60 118
samux 7:6494da2a5c60 119 return success;
samux 7:6494da2a5c60 120 }
samux 7:6494da2a5c60 121
samux 10:cf8fd2b6ca23 122 bool USBMSD::send(HID_REPORT *report) {
samux 10:cf8fd2b6ca23 123 return USBDevice::write(EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE);
samux 10:cf8fd2b6ca23 124 }
samux 10:cf8fd2b6ca23 125
samux 10:cf8fd2b6ca23 126
samux 10:cf8fd2b6ca23 127 bool USBMSD::read(HID_REPORT *report) {
samux 10:cf8fd2b6ca23 128 uint16_t bytesRead = 0;
samux 10:cf8fd2b6ca23 129 bool result;
samux 10:cf8fd2b6ca23 130 result = USBDevice::read(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
samux 10:cf8fd2b6ca23 131 if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
samux 10:cf8fd2b6ca23 132 return false;
samux 10:cf8fd2b6ca23 133 report->length = bytesRead;
samux 10:cf8fd2b6ca23 134 return result;
samux 10:cf8fd2b6ca23 135 }
samux 10:cf8fd2b6ca23 136
samux 10:cf8fd2b6ca23 137
samux 10:cf8fd2b6ca23 138 bool USBMSD::readNB(HID_REPORT *report) {
samux 10:cf8fd2b6ca23 139 uint16_t bytesRead = 0;
samux 10:cf8fd2b6ca23 140 bool result;
samux 10:cf8fd2b6ca23 141 result = USBDevice::readNB(EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE);
samux 10:cf8fd2b6ca23 142 report->length = bytesRead;
samux 10:cf8fd2b6ca23 143 if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
samux 10:cf8fd2b6ca23 144 return false;
samux 10:cf8fd2b6ca23 145 return result;
samux 10:cf8fd2b6ca23 146 }
samux 10:cf8fd2b6ca23 147
samux 10:cf8fd2b6ca23 148
samux 10:cf8fd2b6ca23 149 uint16_t USBMSD::reportDescLength() {
samux 10:cf8fd2b6ca23 150 reportDesc();
samux 10:cf8fd2b6ca23 151 return reportLength;
samux 10:cf8fd2b6ca23 152 }
samux 10:cf8fd2b6ca23 153
samux 10:cf8fd2b6ca23 154
samux 7:6494da2a5c60 155
samux 7:6494da2a5c60 156 bool USBMSD::connect() {
samux 7:6494da2a5c60 157
samux 7:6494da2a5c60 158 //disk initialization
samux 8:534fd41d8cc7 159 disk_initialize();
samux 7:6494da2a5c60 160
samux 7:6494da2a5c60 161 // get block size
samux 8:534fd41d8cc7 162 BlockSize = 512;
samux 7:6494da2a5c60 163 if (BlockSize != 0) {
samux 7:6494da2a5c60 164 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t));
samux 7:6494da2a5c60 165 if (page == NULL)
samux 7:6494da2a5c60 166 return false;
samux 7:6494da2a5c60 167 }
samux 7:6494da2a5c60 168
samux 8:534fd41d8cc7 169 BlockCount = disk_sectors();
samux 10:cf8fd2b6ca23 170
samux 9:9c343b9ee6d8 171 //get memory size
samux 9:9c343b9ee6d8 172 MemorySize = BlockCount * BlockSize;
samux 7:6494da2a5c60 173 if (!MemorySize) {
samux 7:6494da2a5c60 174 return false;
samux 7:6494da2a5c60 175 }
samux 10:cf8fd2b6ca23 176
samux 11:a26e7b7a1221 177 /*printf("blockSize: %d\r\n", BlockSize);
samux 9:9c343b9ee6d8 178 printf("memSize: %d\r\n", MemorySize);
samux 11:a26e7b7a1221 179 printf("number of blocks: %d\r\n", BlockCount);*/
samux 7:6494da2a5c60 180
samux 7:6494da2a5c60 181 //connect the device
samux 7:6494da2a5c60 182 USBDevice::connect();
samux 7:6494da2a5c60 183 return true;
samux 7:6494da2a5c60 184 }
samux 7:6494da2a5c60 185
samux 7:6494da2a5c60 186
samux 7:6494da2a5c60 187 void USBMSD::reset() {
samux 7:6494da2a5c60 188 stage = READ_CBW;
samux 7:6494da2a5c60 189 }
samux 7:6494da2a5c60 190
samux 7:6494da2a5c60 191 uint8_t * USBMSD::getMaxLUN() {
samux 7:6494da2a5c60 192 static uint8_t LUN[] = {0};
samux 7:6494da2a5c60 193 return LUN;
samux 7:6494da2a5c60 194 }
samux 7:6494da2a5c60 195
samux 7:6494da2a5c60 196 // Called in ISR context called when a data is received
samux 7:6494da2a5c60 197 bool USBMSD::EP2_OUT_callback() {
samux 7:6494da2a5c60 198 uint16_t size = 0;
samux 7:6494da2a5c60 199 uint8_t buf[MAX_PACKET_SIZE_EPBULK];
samux 10:cf8fd2b6ca23 200 USBDevice::read(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK);
samux 7:6494da2a5c60 201 switch (stage) {
samux 7:6494da2a5c60 202 // the device has to decode the CBW received
samux 7:6494da2a5c60 203 case READ_CBW:
samux 7:6494da2a5c60 204 CBWDecode(buf, size);
samux 7:6494da2a5c60 205 break;
samux 7:6494da2a5c60 206
samux 7:6494da2a5c60 207 // the device has to receive data from the host
samux 7:6494da2a5c60 208 case PROCESS_CBW:
samux 7:6494da2a5c60 209 switch (cbw.CB[0]) {
samux 7:6494da2a5c60 210 case WRITE10:
samux 7:6494da2a5c60 211 case WRITE12:
samux 7:6494da2a5c60 212 memoryWrite(buf, size);
samux 7:6494da2a5c60 213 break;
samux 7:6494da2a5c60 214 case VERIFY10:
samux 7:6494da2a5c60 215 memoryVerify(buf, size);
samux 7:6494da2a5c60 216 break;
samux 7:6494da2a5c60 217 }
samux 7:6494da2a5c60 218 break;
samux 7:6494da2a5c60 219
samux 7:6494da2a5c60 220 // an error has occured: stall endpoint and send CSW
samux 7:6494da2a5c60 221 default:
samux 7:6494da2a5c60 222 stallEndpoint(EPBULK_OUT);
samux 7:6494da2a5c60 223 csw.Status = CSW_ERROR;
samux 7:6494da2a5c60 224 sendCSW();
samux 7:6494da2a5c60 225 break;
samux 7:6494da2a5c60 226 }
samux 7:6494da2a5c60 227
samux 7:6494da2a5c60 228 //reactivate readings on the OUT bulk endpoint
samux 7:6494da2a5c60 229 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
samux 7:6494da2a5c60 230 return true;
samux 7:6494da2a5c60 231 }
samux 7:6494da2a5c60 232
samux 7:6494da2a5c60 233 // Called in ISR context when a data has been transferred
samux 7:6494da2a5c60 234 bool USBMSD::EP2_IN_callback() {
samux 7:6494da2a5c60 235 switch (stage) {
samux 7:6494da2a5c60 236
samux 7:6494da2a5c60 237 // the device has to send data to the host
samux 7:6494da2a5c60 238 case PROCESS_CBW:
samux 7:6494da2a5c60 239 switch (cbw.CB[0]) {
samux 7:6494da2a5c60 240 case READ10:
samux 7:6494da2a5c60 241 case READ12:
samux 7:6494da2a5c60 242 memoryRead();
samux 7:6494da2a5c60 243 break;
samux 7:6494da2a5c60 244 }
samux 7:6494da2a5c60 245 break;
samux 7:6494da2a5c60 246
samux 7:6494da2a5c60 247 //the device has to send a CSW
samux 7:6494da2a5c60 248 case SEND_CSW:
samux 7:6494da2a5c60 249 sendCSW();
samux 7:6494da2a5c60 250 break;
samux 7:6494da2a5c60 251
samux 7:6494da2a5c60 252 // an error has occured
samux 7:6494da2a5c60 253 case ERROR:
samux 7:6494da2a5c60 254 stallEndpoint(EPBULK_IN);
samux 7:6494da2a5c60 255 sendCSW();
samux 7:6494da2a5c60 256 break;
samux 7:6494da2a5c60 257
samux 7:6494da2a5c60 258 // the host has received the CSW -> we wait a CBW
samux 7:6494da2a5c60 259 case WAIT_CSW:
samux 7:6494da2a5c60 260 stage = READ_CBW;
samux 7:6494da2a5c60 261 break;
samux 7:6494da2a5c60 262 }
samux 7:6494da2a5c60 263 return true;
samux 7:6494da2a5c60 264 }
samux 7:6494da2a5c60 265
samux 7:6494da2a5c60 266
samux 7:6494da2a5c60 267 void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) {
samux 7:6494da2a5c60 268
samux 7:6494da2a5c60 269 if ((addr + size) > MemorySize) {
samux 7:6494da2a5c60 270 size = MemorySize - addr;
samux 7:6494da2a5c60 271 stage = ERROR;
samux 7:6494da2a5c60 272 stallEndpoint(EPBULK_OUT);
samux 7:6494da2a5c60 273 }
samux 7:6494da2a5c60 274
samux 7:6494da2a5c60 275 // we fill an array in RAM of 1 block before writing it in memory
samux 7:6494da2a5c60 276 for (int i = 0; i < size; i++)
samux 7:6494da2a5c60 277 page[addr%BlockSize + i] = buf[i];
samux 7:6494da2a5c60 278
samux 7:6494da2a5c60 279 // if the array is filled, write it in memory
samux 7:6494da2a5c60 280 if (!((addr + size)%BlockSize))
samux 8:534fd41d8cc7 281 disk_write((const char *)page, addr/BlockSize);
samux 7:6494da2a5c60 282
samux 7:6494da2a5c60 283 addr += size;
samux 7:6494da2a5c60 284 length -= size;
samux 7:6494da2a5c60 285 csw.DataResidue -= size;
samux 7:6494da2a5c60 286
samux 7:6494da2a5c60 287 if ((!length) || (stage != PROCESS_CBW)) {
samux 7:6494da2a5c60 288 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED;
samux 7:6494da2a5c60 289 sendCSW();
samux 7:6494da2a5c60 290 }
samux 7:6494da2a5c60 291 }
samux 7:6494da2a5c60 292
samux 7:6494da2a5c60 293 void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) {
samux 7:6494da2a5c60 294 uint32_t n;
samux 7:6494da2a5c60 295
samux 7:6494da2a5c60 296 if ((addr + size) > MemorySize) {
samux 7:6494da2a5c60 297 size = MemorySize - addr;
samux 7:6494da2a5c60 298 stage = ERROR;
samux 7:6494da2a5c60 299 stallEndpoint(EPBULK_OUT);
samux 7:6494da2a5c60 300 }
samux 7:6494da2a5c60 301
samux 7:6494da2a5c60 302 // beginning of a new block -> load a whole block in RAM
samux 7:6494da2a5c60 303 if (!(addr%BlockSize))
samux 8:534fd41d8cc7 304 disk_read((char *)page, addr/BlockSize);
samux 7:6494da2a5c60 305
samux 7:6494da2a5c60 306 // info are in RAM -> no need to re-read memory
samux 7:6494da2a5c60 307 for (n = 0; n < size; n++) {
samux 7:6494da2a5c60 308 if (page[addr%BlockSize + n] != buf[n]) {
samux 7:6494da2a5c60 309 memOK = false;
samux 7:6494da2a5c60 310 break;
samux 7:6494da2a5c60 311 }
samux 7:6494da2a5c60 312 }
samux 7:6494da2a5c60 313
samux 7:6494da2a5c60 314 addr += size;
samux 7:6494da2a5c60 315 length -= size;
samux 7:6494da2a5c60 316 csw.DataResidue -= size;
samux 7:6494da2a5c60 317
samux 7:6494da2a5c60 318 if ( !length || (stage != PROCESS_CBW)) {
samux 7:6494da2a5c60 319 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED;
samux 7:6494da2a5c60 320 sendCSW();
samux 7:6494da2a5c60 321 }
samux 7:6494da2a5c60 322 }
samux 7:6494da2a5c60 323
samux 7:6494da2a5c60 324
samux 7:6494da2a5c60 325 bool USBMSD::inquiryRequest (void) {
samux 7:6494da2a5c60 326 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01,
samux 7:6494da2a5c60 327 36 - 4, 0x80, 0x00, 0x00,
samux 11:a26e7b7a1221 328 'M', 'b', 'e', 'd', '.', 'o', 'r', 'g',
samux 11:a26e7b7a1221 329 'M', 'b', 'e', 'd', ' ', 'U', 'S', 'B', ' ', 'D', 'i', 's', 'k', ' ', ' ', ' ',
samux 7:6494da2a5c60 330 '1', '.', '0', ' ',
samux 7:6494da2a5c60 331 };
samux 7:6494da2a5c60 332 if (!write(inquiry, sizeof(inquiry))) {
samux 7:6494da2a5c60 333 return false;
samux 7:6494da2a5c60 334 }
samux 7:6494da2a5c60 335 return true;
samux 7:6494da2a5c60 336 }
samux 7:6494da2a5c60 337
samux 7:6494da2a5c60 338
samux 7:6494da2a5c60 339 bool USBMSD::readFormatCapacity() {
samux 7:6494da2a5c60 340 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08,
samux 7:6494da2a5c60 341 (BlockCount >> 24) & 0xff,
samux 7:6494da2a5c60 342 (BlockCount >> 16) & 0xff,
samux 7:6494da2a5c60 343 (BlockCount >> 8) & 0xff,
samux 7:6494da2a5c60 344 (BlockCount >> 0) & 0xff,
samux 7:6494da2a5c60 345
samux 7:6494da2a5c60 346 0x02,
samux 7:6494da2a5c60 347 (BlockSize >> 16) & 0xff,
samux 7:6494da2a5c60 348 (BlockSize >> 8) & 0xff,
samux 7:6494da2a5c60 349 (BlockSize >> 0) & 0xff,
samux 7:6494da2a5c60 350 };
samux 7:6494da2a5c60 351 if (!write(capacity, sizeof(capacity))) {
samux 7:6494da2a5c60 352 return false;
samux 7:6494da2a5c60 353 }
samux 7:6494da2a5c60 354 return true;
samux 7:6494da2a5c60 355 }
samux 7:6494da2a5c60 356
samux 7:6494da2a5c60 357
samux 7:6494da2a5c60 358 bool USBMSD::readCapacity (void) {
samux 7:6494da2a5c60 359 uint8_t capacity[] = {
samux 7:6494da2a5c60 360 ((BlockCount - 1) >> 24) & 0xff,
samux 7:6494da2a5c60 361 ((BlockCount - 1) >> 16) & 0xff,
samux 7:6494da2a5c60 362 ((BlockCount - 1) >> 8) & 0xff,
samux 7:6494da2a5c60 363 ((BlockCount - 1) >> 0) & 0xff,
samux 7:6494da2a5c60 364
samux 7:6494da2a5c60 365 (BlockSize >> 24) & 0xff,
samux 7:6494da2a5c60 366 (BlockSize >> 16) & 0xff,
samux 7:6494da2a5c60 367 (BlockSize >> 8) & 0xff,
samux 7:6494da2a5c60 368 (BlockSize >> 0) & 0xff,
samux 7:6494da2a5c60 369 };
samux 7:6494da2a5c60 370 if (!write(capacity, sizeof(capacity))) {
samux 7:6494da2a5c60 371 return false;
samux 7:6494da2a5c60 372 }
samux 7:6494da2a5c60 373 return true;
samux 7:6494da2a5c60 374 }
samux 7:6494da2a5c60 375
samux 7:6494da2a5c60 376 bool USBMSD::write (uint8_t * buf, uint16_t size) {
samux 7:6494da2a5c60 377
samux 7:6494da2a5c60 378 if (size >= cbw.DataLength) {
samux 7:6494da2a5c60 379 size = cbw.DataLength;
samux 7:6494da2a5c60 380 }
samux 7:6494da2a5c60 381 stage = SEND_CSW;
samux 7:6494da2a5c60 382
samux 11:a26e7b7a1221 383 writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK);
samux 7:6494da2a5c60 384
samux 7:6494da2a5c60 385 csw.DataResidue -= size;
samux 7:6494da2a5c60 386 csw.Status = CSW_PASSED;
samux 7:6494da2a5c60 387 return true;
samux 7:6494da2a5c60 388 }
samux 7:6494da2a5c60 389
samux 7:6494da2a5c60 390
samux 7:6494da2a5c60 391 bool USBMSD::modeSense6 (void) {
samux 7:6494da2a5c60 392 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 };
samux 7:6494da2a5c60 393 if (!write(sense6, sizeof(sense6))) {
samux 7:6494da2a5c60 394 return false;
samux 7:6494da2a5c60 395 }
samux 7:6494da2a5c60 396 return true;
samux 7:6494da2a5c60 397 }
samux 7:6494da2a5c60 398
samux 7:6494da2a5c60 399 void USBMSD::sendCSW() {
samux 7:6494da2a5c60 400 csw.Signature = CSW_Signature;
samux 7:6494da2a5c60 401 writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK);
samux 7:6494da2a5c60 402 stage = WAIT_CSW;
samux 7:6494da2a5c60 403 }
samux 7:6494da2a5c60 404
samux 7:6494da2a5c60 405 bool USBMSD::requestSense (void) {
samux 7:6494da2a5c60 406 uint8_t request_sense[] = {
samux 7:6494da2a5c60 407 0x70, // Response Code
samux 7:6494da2a5c60 408 0x00,
samux 7:6494da2a5c60 409 0x05, // Sense Key: illegal request
samux 7:6494da2a5c60 410 0x00,
samux 7:6494da2a5c60 411 0x00,
samux 7:6494da2a5c60 412 0x00,
samux 7:6494da2a5c60 413 0x00,
samux 7:6494da2a5c60 414 0x0A, // Additional Length
samux 7:6494da2a5c60 415 0x00,
samux 7:6494da2a5c60 416 0x00,
samux 7:6494da2a5c60 417 0x00,
samux 7:6494da2a5c60 418 0x00,
samux 7:6494da2a5c60 419 0x30, // ASC
samux 7:6494da2a5c60 420 0x01, // ASCQ
samux 7:6494da2a5c60 421 0x00,
samux 7:6494da2a5c60 422 0x00,
samux 7:6494da2a5c60 423 0x00,
samux 7:6494da2a5c60 424 0x00,
samux 7:6494da2a5c60 425 };
samux 7:6494da2a5c60 426
samux 7:6494da2a5c60 427 if (!write(request_sense, sizeof(request_sense))) {
samux 7:6494da2a5c60 428 return false;
samux 7:6494da2a5c60 429 }
samux 7:6494da2a5c60 430
samux 7:6494da2a5c60 431 return true;
samux 7:6494da2a5c60 432 }
samux 7:6494da2a5c60 433
samux 7:6494da2a5c60 434 void USBMSD::fail() {
samux 7:6494da2a5c60 435 csw.Status = CSW_FAILED;
samux 7:6494da2a5c60 436 sendCSW();
samux 7:6494da2a5c60 437 }
samux 7:6494da2a5c60 438
samux 11:a26e7b7a1221 439
samux 7:6494da2a5c60 440 void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) {
samux 7:6494da2a5c60 441 if (size == sizeof(cbw)) {
samux 7:6494da2a5c60 442 memcpy((uint8_t *)&cbw, buf, size);
samux 7:6494da2a5c60 443 if (cbw.Signature == CBW_Signature) {
samux 7:6494da2a5c60 444 csw.Tag = cbw.Tag;
samux 7:6494da2a5c60 445 csw.DataResidue = cbw.DataLength;
samux 7:6494da2a5c60 446 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) {
samux 7:6494da2a5c60 447 fail();
samux 7:6494da2a5c60 448 } else {
samux 7:6494da2a5c60 449 switch (cbw.CB[0]) {
samux 7:6494da2a5c60 450 case TEST_UNIT_READY:
samux 7:6494da2a5c60 451 testUnitReady();
samux 7:6494da2a5c60 452 break;
samux 7:6494da2a5c60 453 case REQUEST_SENSE:
samux 7:6494da2a5c60 454 requestSense();
samux 7:6494da2a5c60 455 break;
samux 7:6494da2a5c60 456 case INQUIRY:
samux 7:6494da2a5c60 457 inquiryRequest();
samux 7:6494da2a5c60 458 break;
samux 7:6494da2a5c60 459 case MODE_SENSE6:
samux 7:6494da2a5c60 460 modeSense6();
samux 7:6494da2a5c60 461 break;
samux 7:6494da2a5c60 462 case READ_FORMAT_CAPACITIES:
samux 7:6494da2a5c60 463 readFormatCapacity();
samux 7:6494da2a5c60 464 break;
samux 7:6494da2a5c60 465 case READ_CAPACITY:
samux 7:6494da2a5c60 466 readCapacity();
samux 7:6494da2a5c60 467 break;
samux 7:6494da2a5c60 468 case READ10:
samux 7:6494da2a5c60 469 case READ12:
samux 7:6494da2a5c60 470 if (infoTransfer()) {
samux 7:6494da2a5c60 471 if ((cbw.Flags & 0x80)) {
samux 7:6494da2a5c60 472 stage = PROCESS_CBW;
samux 7:6494da2a5c60 473 memoryRead();
samux 7:6494da2a5c60 474 } else {
samux 7:6494da2a5c60 475 stallEndpoint(EPBULK_OUT);
samux 7:6494da2a5c60 476 csw.Status = CSW_ERROR;
samux 7:6494da2a5c60 477 sendCSW();
samux 7:6494da2a5c60 478 }
samux 7:6494da2a5c60 479 }
samux 7:6494da2a5c60 480 break;
samux 7:6494da2a5c60 481 case WRITE10:
samux 7:6494da2a5c60 482 case WRITE12:
samux 7:6494da2a5c60 483 if (infoTransfer()) {
samux 7:6494da2a5c60 484 if (!(cbw.Flags & 0x80)) {
samux 7:6494da2a5c60 485 stage = PROCESS_CBW;
samux 7:6494da2a5c60 486 } else {
samux 7:6494da2a5c60 487 stallEndpoint(EPBULK_IN);
samux 7:6494da2a5c60 488 csw.Status = CSW_ERROR;
samux 7:6494da2a5c60 489 sendCSW();
samux 7:6494da2a5c60 490 }
samux 7:6494da2a5c60 491 }
samux 7:6494da2a5c60 492 break;
samux 7:6494da2a5c60 493 case VERIFY10:
samux 7:6494da2a5c60 494 if (!(cbw.CB[1] & 0x02)) {
samux 7:6494da2a5c60 495 csw.Status = CSW_PASSED;
samux 7:6494da2a5c60 496 sendCSW();
samux 7:6494da2a5c60 497 break;
samux 7:6494da2a5c60 498 }
samux 7:6494da2a5c60 499 if (infoTransfer()) {
samux 7:6494da2a5c60 500 if (!(cbw.Flags & 0x80)) {
samux 7:6494da2a5c60 501 stage = PROCESS_CBW;
samux 7:6494da2a5c60 502 memOK = true;
samux 7:6494da2a5c60 503 } else {
samux 7:6494da2a5c60 504 stallEndpoint(EPBULK_IN);
samux 7:6494da2a5c60 505 csw.Status = CSW_ERROR;
samux 7:6494da2a5c60 506 sendCSW();
samux 7:6494da2a5c60 507 }
samux 7:6494da2a5c60 508 }
samux 7:6494da2a5c60 509 break;
samux 7:6494da2a5c60 510 default:
samux 7:6494da2a5c60 511 fail();
samux 7:6494da2a5c60 512 break;
samux 7:6494da2a5c60 513 }
samux 7:6494da2a5c60 514 }
samux 7:6494da2a5c60 515 }
samux 7:6494da2a5c60 516 }
samux 7:6494da2a5c60 517 }
samux 7:6494da2a5c60 518
samux 7:6494da2a5c60 519 void USBMSD::testUnitReady (void) {
samux 7:6494da2a5c60 520
samux 7:6494da2a5c60 521 if (cbw.DataLength != 0) {
samux 7:6494da2a5c60 522 if ((cbw.Flags & 0x80) != 0) {
samux 7:6494da2a5c60 523 stallEndpoint(EPBULK_IN);
samux 7:6494da2a5c60 524 } else {
samux 7:6494da2a5c60 525 stallEndpoint(EPBULK_OUT);
samux 7:6494da2a5c60 526 }
samux 7:6494da2a5c60 527 }
samux 7:6494da2a5c60 528
samux 7:6494da2a5c60 529 csw.Status = CSW_PASSED;
samux 7:6494da2a5c60 530 sendCSW();
samux 7:6494da2a5c60 531 }
samux 7:6494da2a5c60 532
samux 7:6494da2a5c60 533
samux 7:6494da2a5c60 534 void USBMSD::memoryRead (void) {
samux 7:6494da2a5c60 535 uint32_t n;
samux 7:6494da2a5c60 536
samux 7:6494da2a5c60 537 n = (length > MAX_PACKET) ? MAX_PACKET : length;
samux 7:6494da2a5c60 538
samux 7:6494da2a5c60 539 if ((addr + n) > MemorySize) {
samux 7:6494da2a5c60 540 n = MemorySize - addr;
samux 7:6494da2a5c60 541 stage = ERROR;
samux 7:6494da2a5c60 542 }
samux 7:6494da2a5c60 543
samux 7:6494da2a5c60 544 // we read an entire block
samux 7:6494da2a5c60 545 if (!(addr%BlockSize))
samux 8:534fd41d8cc7 546 disk_read((char *)page, addr/BlockSize);
samux 7:6494da2a5c60 547
samux 7:6494da2a5c60 548 // write data which are in RAM
samux 7:6494da2a5c60 549 writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK);
samux 7:6494da2a5c60 550
samux 7:6494da2a5c60 551 addr += n;
samux 7:6494da2a5c60 552 length -= n;
samux 7:6494da2a5c60 553
samux 7:6494da2a5c60 554 csw.DataResidue -= n;
samux 7:6494da2a5c60 555
samux 7:6494da2a5c60 556 if ( !length || (stage != PROCESS_CBW)) {
samux 7:6494da2a5c60 557 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
samux 7:6494da2a5c60 558 sendCSW();
samux 7:6494da2a5c60 559 }
samux 7:6494da2a5c60 560 }
samux 7:6494da2a5c60 561
samux 7:6494da2a5c60 562
samux 7:6494da2a5c60 563 bool USBMSD::infoTransfer (void) {
samux 7:6494da2a5c60 564 uint32_t n;
samux 7:6494da2a5c60 565
samux 7:6494da2a5c60 566 // Logical Block Address of First Block
samux 7:6494da2a5c60 567 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0);
samux 7:6494da2a5c60 568
samux 7:6494da2a5c60 569 addr = n * BlockSize;
samux 7:6494da2a5c60 570
samux 7:6494da2a5c60 571 // Number of Blocks to transfer
samux 7:6494da2a5c60 572 switch (cbw.CB[0]) {
samux 7:6494da2a5c60 573 case READ10:
samux 7:6494da2a5c60 574 case WRITE10:
samux 7:6494da2a5c60 575 case VERIFY10:
samux 7:6494da2a5c60 576 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0);
samux 7:6494da2a5c60 577 break;
samux 7:6494da2a5c60 578
samux 7:6494da2a5c60 579 case READ12:
samux 7:6494da2a5c60 580 case WRITE12:
samux 7:6494da2a5c60 581 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0);
samux 7:6494da2a5c60 582 break;
samux 7:6494da2a5c60 583 }
samux 7:6494da2a5c60 584
samux 7:6494da2a5c60 585 length = n * BlockSize;
samux 7:6494da2a5c60 586
samux 7:6494da2a5c60 587 if (!cbw.DataLength) { // host requests no data
samux 7:6494da2a5c60 588 csw.Status = CSW_FAILED;
samux 7:6494da2a5c60 589 sendCSW();
samux 7:6494da2a5c60 590 return false;
samux 7:6494da2a5c60 591 }
samux 7:6494da2a5c60 592
samux 7:6494da2a5c60 593 if (cbw.DataLength != length) {
samux 7:6494da2a5c60 594 if ((cbw.Flags & 0x80) != 0) {
samux 7:6494da2a5c60 595 stallEndpoint(EPBULK_IN);
samux 7:6494da2a5c60 596 } else {
samux 7:6494da2a5c60 597 stallEndpoint(EPBULK_OUT);
samux 7:6494da2a5c60 598 }
samux 7:6494da2a5c60 599
samux 7:6494da2a5c60 600 csw.Status = CSW_FAILED;
samux 7:6494da2a5c60 601 sendCSW();
samux 7:6494da2a5c60 602 return false;
samux 7:6494da2a5c60 603 }
samux 7:6494da2a5c60 604
samux 7:6494da2a5c60 605 return true;
samux 7:6494da2a5c60 606 }
samux 7:6494da2a5c60 607
samux 7:6494da2a5c60 608
samux 7:6494da2a5c60 609
samux 7:6494da2a5c60 610
samux 7:6494da2a5c60 611
samux 7:6494da2a5c60 612 // Called in ISR context
samux 7:6494da2a5c60 613 // Set configuration. Return false if the
samux 7:6494da2a5c60 614 // configuration is not supported.
samux 7:6494da2a5c60 615 bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) {
samux 7:6494da2a5c60 616 if (configuration != DEFAULT_CONFIGURATION) {
samux 7:6494da2a5c60 617 return false;
samux 7:6494da2a5c60 618 }
samux 7:6494da2a5c60 619
samux 7:6494da2a5c60 620 // Configure endpoints > 0
samux 10:cf8fd2b6ca23 621 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
samux 10:cf8fd2b6ca23 622 addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
samux 10:cf8fd2b6ca23 623
samux 7:6494da2a5c60 624 addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
samux 7:6494da2a5c60 625 addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
samux 7:6494da2a5c60 626
samux 7:6494da2a5c60 627 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
samux 10:cf8fd2b6ca23 628 readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
samux 7:6494da2a5c60 629 return true;
samux 7:6494da2a5c60 630 }
samux 7:6494da2a5c60 631
samux 7:6494da2a5c60 632
samux 7:6494da2a5c60 633 uint8_t * USBMSD::stringIinterfaceDesc() {
samux 7:6494da2a5c60 634 static uint8_t stringIinterfaceDescriptor[] = {
samux 7:6494da2a5c60 635 0x08, //bLength
samux 7:6494da2a5c60 636 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 7:6494da2a5c60 637 'M',0,'S',0,'D',0 //bString iInterface - MSD
samux 7:6494da2a5c60 638 };
samux 7:6494da2a5c60 639 return stringIinterfaceDescriptor;
samux 7:6494da2a5c60 640 }
samux 7:6494da2a5c60 641
samux 7:6494da2a5c60 642 uint8_t * USBMSD::stringIproductDesc() {
samux 7:6494da2a5c60 643 static uint8_t stringIproductDescriptor[] = {
samux 11:a26e7b7a1221 644 0x1e, //bLength
samux 7:6494da2a5c60 645 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 11:a26e7b7a1221 646 'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D', 0, ' ', 0, '&', 0, ' ', 0, 'H', 0, 'I', 0, 'D', 0 //bString iProduct - Mbed Audio
samux 7:6494da2a5c60 647 };
samux 7:6494da2a5c60 648 return stringIproductDescriptor;
samux 7:6494da2a5c60 649 }
samux 7:6494da2a5c60 650
samux 10:cf8fd2b6ca23 651 uint8_t * USBMSD::reportDesc() {
samux 10:cf8fd2b6ca23 652 static uint8_t reportDescriptor[] = {
samux 10:cf8fd2b6ca23 653 0x06, LSB(0xFFAB), MSB(0xFFAB),
samux 10:cf8fd2b6ca23 654 0x0A, LSB(0x0200), MSB(0x0200),
samux 10:cf8fd2b6ca23 655 0xA1, 0x01, // Collection 0x01
samux 10:cf8fd2b6ca23 656 0x75, 0x08, // report size = 8 bits
samux 10:cf8fd2b6ca23 657 0x15, 0x00, // logical minimum = 0
samux 10:cf8fd2b6ca23 658 0x26, 0xFF, 0x00, // logical maximum = 255
samux 10:cf8fd2b6ca23 659 0x95, 64, // report count
samux 10:cf8fd2b6ca23 660 0x09, 0x01, // usage
samux 10:cf8fd2b6ca23 661 0x81, 0x02, // Input (array)
samux 10:cf8fd2b6ca23 662 0x95, 64, // report count
samux 10:cf8fd2b6ca23 663 0x09, 0x02, // usage
samux 10:cf8fd2b6ca23 664 0x91, 0x02, // Output (array)
samux 10:cf8fd2b6ca23 665 0xC0 // end collection
samux 10:cf8fd2b6ca23 666
samux 10:cf8fd2b6ca23 667 };
samux 10:cf8fd2b6ca23 668 reportLength = sizeof(reportDescriptor);
samux 10:cf8fd2b6ca23 669 return reportDescriptor;
samux 10:cf8fd2b6ca23 670 }
samux 10:cf8fd2b6ca23 671
samux 10:cf8fd2b6ca23 672 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
samux 10:cf8fd2b6ca23 673 + (2 * INTERFACE_DESCRIPTOR_LENGTH) \
samux 10:cf8fd2b6ca23 674 + (1 * HID_DESCRIPTOR_LENGTH) \
samux 10:cf8fd2b6ca23 675 + (4 * ENDPOINT_DESCRIPTOR_LENGTH))
samux 7:6494da2a5c60 676
samux 7:6494da2a5c60 677 uint8_t * USBMSD::configurationDesc() {
samux 7:6494da2a5c60 678 static uint8_t configDescriptor[] = {
samux 10:cf8fd2b6ca23 679 CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
samux 10:cf8fd2b6ca23 680 CONFIGURATION_DESCRIPTOR, // bDescriptorType
samux 10:cf8fd2b6ca23 681 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
samux 10:cf8fd2b6ca23 682 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
samux 10:cf8fd2b6ca23 683 0x02, // bNumInterfaces (2 interfaces)
samux 10:cf8fd2b6ca23 684 DEFAULT_CONFIGURATION, // bConfigurationValue
samux 10:cf8fd2b6ca23 685 0x00, // iConfiguration
samux 10:cf8fd2b6ca23 686 C_RESERVED | C_SELF_POWERED, // bmAttributes
samux 10:cf8fd2b6ca23 687 C_POWER(0), // bMaxPower
samux 7:6494da2a5c60 688
samux 10:cf8fd2b6ca23 689
samux 10:cf8fd2b6ca23 690 // interface 1: HID
samux 10:cf8fd2b6ca23 691 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 10:cf8fd2b6ca23 692 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 11:a26e7b7a1221 693 0x00, // bInterfaceNumber
samux 10:cf8fd2b6ca23 694 0x00, // bAlternateSetting
samux 10:cf8fd2b6ca23 695 0x02, // bNumEndpoints
samux 10:cf8fd2b6ca23 696 HID_CLASS, // bInterfaceClass
samux 10:cf8fd2b6ca23 697 HID_SUBCLASS_NONE, // bInterfaceSubClass
samux 10:cf8fd2b6ca23 698 HID_PROTOCOL_NONE, // bInterfaceProtocol
samux 10:cf8fd2b6ca23 699 0x00, // iInterface
samux 10:cf8fd2b6ca23 700
samux 10:cf8fd2b6ca23 701 HID_DESCRIPTOR_LENGTH, // bLength
samux 10:cf8fd2b6ca23 702 HID_DESCRIPTOR, // bDescriptorType
samux 10:cf8fd2b6ca23 703 LSB(HID_VERSION_1_11), // bcdHID (LSB)
samux 10:cf8fd2b6ca23 704 MSB(HID_VERSION_1_11), // bcdHID (MSB)
samux 10:cf8fd2b6ca23 705 0x00, // bCountryCode
samux 10:cf8fd2b6ca23 706 0x01, // bNumDescriptors
samux 10:cf8fd2b6ca23 707 REPORT_DESCRIPTOR, // bDescriptorType
samux 10:cf8fd2b6ca23 708 LSB(this->reportDescLength()), // wDescriptorLength (LSB)
samux 10:cf8fd2b6ca23 709 MSB(this->reportDescLength()), // wDescriptorLength (MSB)
samux 10:cf8fd2b6ca23 710
samux 10:cf8fd2b6ca23 711 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 10:cf8fd2b6ca23 712 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 10:cf8fd2b6ca23 713 PHY_TO_DESC(EPINT_IN), // bEndpointAddress
samux 10:cf8fd2b6ca23 714 E_INTERRUPT, // bmAttributes
samux 10:cf8fd2b6ca23 715 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
samux 10:cf8fd2b6ca23 716 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
samux 10:cf8fd2b6ca23 717 10, // bInterval (milliseconds)
samux 10:cf8fd2b6ca23 718
samux 10:cf8fd2b6ca23 719 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 10:cf8fd2b6ca23 720 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 10:cf8fd2b6ca23 721 PHY_TO_DESC(EPINT_OUT), // bEndpointAddress
samux 10:cf8fd2b6ca23 722 E_INTERRUPT, // bmAttributes
samux 10:cf8fd2b6ca23 723 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
samux 10:cf8fd2b6ca23 724 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
samux 10:cf8fd2b6ca23 725 10, // bInterval (milliseconds)
samux 10:cf8fd2b6ca23 726
samux 11:a26e7b7a1221 727 // Interface 1, Alternate Setting 0, MSC Class
samux 11:a26e7b7a1221 728 9, // bLength
samux 11:a26e7b7a1221 729 4, // bDescriptorType
samux 11:a26e7b7a1221 730 0x01, // bInterfaceNumber
samux 11:a26e7b7a1221 731 0x00, // bAlternateSetting
samux 11:a26e7b7a1221 732 0x02, // bNumEndpoints
samux 11:a26e7b7a1221 733 0x08, // bInterfaceClass
samux 11:a26e7b7a1221 734 0x06, // bInterfaceSubClass
samux 11:a26e7b7a1221 735 0x50, // bInterfaceProtocol
samux 11:a26e7b7a1221 736 0x00, // iInterface
samux 11:a26e7b7a1221 737
samux 11:a26e7b7a1221 738 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
samux 11:a26e7b7a1221 739 7, // bLength
samux 11:a26e7b7a1221 740 5, // bDescriptorType
samux 11:a26e7b7a1221 741 PHY_TO_DESC(EPBULK_IN), // bEndpointAddress
samux 11:a26e7b7a1221 742 0x02, // bmAttributes (0x02=bulk)
samux 11:a26e7b7a1221 743 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
samux 11:a26e7b7a1221 744 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
samux 11:a26e7b7a1221 745 0, // bInterval
samux 11:a26e7b7a1221 746
samux 11:a26e7b7a1221 747 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
samux 11:a26e7b7a1221 748 7, // bLength
samux 11:a26e7b7a1221 749 5, // bDescriptorType
samux 11:a26e7b7a1221 750 PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress
samux 11:a26e7b7a1221 751 0x02, // bmAttributes (0x02=bulk)
samux 11:a26e7b7a1221 752 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
samux 11:a26e7b7a1221 753 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
samux 11:a26e7b7a1221 754 0, // bInterval
samux 11:a26e7b7a1221 755
samux 11:a26e7b7a1221 756
samux 7:6494da2a5c60 757 };
samux 7:6494da2a5c60 758 return configDescriptor;
samux 7:6494da2a5c60 759 }