USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Wed Nov 16 11:06:27 2011 +0000
Revision:
10:cf8fd2b6ca23
Parent:
9:9c343b9ee6d8
Child:
11:a26e7b7a1221
YES!!!!!!!!!!!!!!!!!! msd with sd card and hid generic device works

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